예제 #1
0
    def test_complex_search_goes_through_unmodified(self):
        config = getUtility(ISolrConnectionConfig)
        config.search_pattern = '{irrelevant}'

        query = dict(SearchableText='foo AND bar')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': 'foo AND bar'},
            query
        )
예제 #2
0
    def test_simple_search_results_in_value_without_wildcards(self):
        config = getUtility(ISolrConnectionConfig)
        config.search_pattern = '{value}'

        query = dict(SearchableText='foo bar')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(['(foo bar)'])},
            query
        )
예제 #3
0
    def test_simple_terms_are_handled_the_same_as_simple_searches(self):
        config = getUtility(ISolrConnectionConfig)
        config.search_pattern = '{value} OR {value_lwc} OR {value_twc}'

        # Simple term
        query = dict(SearchableText='foo')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(['foo OR (*foo) OR (foo*)'])},
            query
        )

        # Simple search
        query = dict(SearchableText='foo bar')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(
                ['(foo bar) OR (*foo *bar) OR (foo* bar*)'])},
            query
        )
예제 #4
0
    def test_search_pattern_value_is_lowercase(self):
        config = getUtility(ISolrConnectionConfig)
        config.search_pattern = 'Title:{value}'

        query = dict(SearchableText='Pass')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(['Title:pass'])},
            query
        )

        query = dict(SearchableText='Pass*')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(['Title:pass'])},
            query
        )

        query = dict(SearchableText='Pass port')
        mangleQuery(query, config, self.schema)
        self.assertEquals(
            {'SearchableText': set(['Title:(pass port)'])},
            query
        )
예제 #5
0
def buildQueryAndParameters(self, default=None, **args):
    """ helper to build a querystring for simple use-cases """
    schema = self.getManager().getSchema() or {}
    config = self.getConfig()

    params = subtractQueryParameters(args)
    params = cleanupQueryParameters(params, schema)

    languageFilter(args)
    prepareData(args)
    mangleQuery(args, config, schema)

    logger.debug('building query for "%r", %r', default, args)
    defaultSearchField = getattr(schema, 'defaultSearchField', None)

    if default is not None and defaultSearchField is not None:
        args[None] = default

    query = {}

    for name, value in sorted(args.items()):
        field = schema.get(name or defaultSearchField, None)
        if field is None or not field.indexed:
            logger.info(
                'dropping unknown search attribute "%s" '
                ' (%r) for query: %r', name, value, args
            )
            continue
        if isinstance(value, bool):
            value = str(value).lower()
        elif not value:     # solr doesn't like empty fields (+foo:"")
            if not name:
                continue
            logger.info(
                'empty search term form "%s:%s", aborting buildQuery' % (
                    name,
                    value
                )
            )
            return {}, params
        elif field.class_ == 'solr.BoolField':
            if not isinstance(value, (tuple, list)):
                value = [value]
            falses = '0', 'False', MV
            true = lambda v: bool(v) and v not in falses
            value = set(map(true, value))
            if not len(value) == 1:
                assert len(value) == 2      # just to make sure
                continue                    # skip when "true or false"
            value = str(value.pop()).lower()
        elif isinstance(value, (tuple, list)):
            # list items should be treated as literals, but
            # nevertheless only get quoted when necessary
            def quoteitem(term):
                if isinstance(term, unicode):
                    term = term.encode('utf-8')
                quoted = quote(term)
                if not quoted.startswith('"') and not quoted == term:
                    quoted = quote('"' + term + '"')
                return quoted
            value = '(%s)' % ' OR '.join(map(quoteitem, value))
        elif isinstance(value, set):        # sets are taken literally
            if len(value) == 1:
                query[name] = ''.join(value)
            else:
                query[name] = '(%s)' % ' OR '.join(value)
            if '/' in query[name]:
                query[name] = query[name].replace('/', '\\/')
            continue
        elif isinstance(value, basestring):
            if field.class_ == 'solr.TextField':
                if isWildCard(value):
                    value = prepare_wildcard(value)
                value = quote(value, textfield=True)
                # if we have an intra-word hyphen, we need quotes
                if '\\-' in value or '\\+' in value:
                    if value[0] != '"':
                        value = '"%s"' % value
            else:
                value = quote(value)
            if not value:   # don't search for empty strings, even quoted
                continue
        else:
            logger.info(
                'skipping unsupported value "%r" (%s)', value, name
            )
            continue
        if name is None:
            if value and value[0] not in '+-':
                value = '+%s' % value
        else:
            value = '+%s:%s' % (name, value)

        query[name] = value
    logger.debug('built query "%s"', query)

    if query:
        optimizeQueryParameters(query, params)
    return query, params