Ejemplo n.º 1
0
def test_query_clone():
    bool = query.Bool(must=[query.Match(x=42)], should=[query.Match(g="v2")], must_not=[query.Match(title='value')])
    bool_clone = bool._clone()

    assert bool == bool_clone
    assert bool is not bool_clone
    assert bool.must[0] is not bool_clone.must[0]
Ejemplo n.º 2
0
def test_two_queries_make_a_bool():
    q1 = query.Match(f='value1')
    q2 = query.Match(message={"query": "this is a test", "opeartor": "and"})
    q = q1 & q2

    assert isinstance(q, query.Bool)
    assert [q1, q2] == q.must
Ejemplo n.º 3
0
def test_query_and_query_creates_bool():
    q1 = query.Match(f=42)
    q2 = query.Match(g=47)

    q = q1 & q2
    assert isinstance(q, query.Bool)
    assert q.must == [q1, q2]
Ejemplo n.º 4
0
def test_or_bool_doesnt_loop_infinitely_issue_96():
    q = ~query.Match(f=42) | ~query.Match(f=47)

    assert q == query.Bool(should=[
        query.Bool(must_not=[query.Match(f=42)]),
        query.Bool(must_not=[query.Match(f=47)])
    ])
Ejemplo n.º 5
0
    def secondary_should_rules(self, search_query, analyzer):
        """Return "secondary" should rules for the query.

        These are the ones using the weakest boosts, they are applied to fields
        containing more text like description, summary and tags.
        """
        should = [
            query.Match(summary={'query': search_query, 'boost': 0.8,
                                 'type': 'phrase'}),
            query.Match(description={'query': search_query, 'boost': 0.3,
                                     'type': 'phrase'}),
            query.Match(tags={'query': search_query.split(), 'boost': 0.1}),
        ]

        # For description and summary, also search in translated field with the
        # right language and analyzer.
        if analyzer:
            should.extend([
                query.Match(**{'summary_%s' % analyzer: {
                    'query': search_query, 'boost': 0.6, 'type': 'phrase',
                    'analyzer': analyzer}}),
                query.Match(**{'description_%s' % analyzer: {
                    'query': search_query, 'boost': 0.6, 'type': 'phrase',
                    'analyzer': analyzer}})
            ])

        return should
Ejemplo n.º 6
0
 def test_current_locale_results(self):
     self.refresh()
     results = (WikiDocumentType.search().query(
         query.Match(title='article')
         | query.Match(content='article')).filter('term', locale='en-US'))
     for doc in results.execute():
         eq_('en-US', doc.locale)
Ejemplo n.º 7
0
def test_bool_query_gets_inverted_internally():
    q = query.Bool(must_not=[query.Match(f=42)], must=[query.Match(g='v')])

    assert ~q == query.Bool(should=[
        # negating must
        query.Bool(must_not=[query.Match(g='v')]),
        # negating must_not
        query.Match(f=42),
    ])
Ejemplo n.º 8
0
 def test_current_locale_results(self):
     self.refresh()
     results = (
         WikiDocumentType.search()
         .query(query.Match(title="article") | query.Match(content="article"))
         .filter("term", locale="en-US")
     )
     for doc in results.execute():
         assert "en-US" == doc.locale
Ejemplo n.º 9
0
def test_bool_will_append_another_query_with_or():
    qb = query.Bool(should=[
        query.Match(f='v'),
        query.Match(f='v2'),
    ])
    q = query.Match(g=42)

    assert (q | qb) == query.Bool(
        should=[query.Match(f='v'), query.Match(f='v2'), q])
Ejemplo n.º 10
0
def test_search_query_combines_query():
    s = search.Search()

    s2 = s.query('match', f=42)
    assert s2.query._proxied == query.Match(f=42)
    assert s.query._proxied is None

    s3 = s2.query('match', f=43)
    assert s2.query._proxied == query.Match(f=42)
    assert s3.query._proxied == query.Bool(must=[query.Match(f=42), query.Match(f=43)])
Ejemplo n.º 11
0
def test_bool_and_bool():
    qt1, qt2, qt3 = query.Match(f=1), query.Match(f=2), query.Match(f=3)

    q1 = query.Bool(must=[qt1], should=[qt2])
    q2 = query.Bool(must_not=[qt3])
    assert q1 & q2 == query.Bool(must=[qt1], must_not=[qt3], should=[qt2])

    q1 = query.Bool(must=[qt1], should=[qt1, qt2])
    q2 = query.Bool(should=[qt3])
    assert q1 & q2 == query.Bool(must=[qt1], should=[query.Bool(should=[qt1, qt2]), qt3])
Ejemplo n.º 12
0
def test_two_bools_are_combined():
    q1 = query.Bool(must=[query.MatchAll(), query.Match(f=42)], should=[query.Match(g="v")])
    q2 = query.Bool(must=[query.Match(x=42)], should=[query.Match(g="v2")], must_not=[query.Match(title='value')])

    q = q1 + q2
    assert isinstance(q, query.Bool)
    assert q.must == [query.MatchAll(), query.Match(f=42), query.Match(x=42)]
    assert q.should == [query.Match(g="v"), query.Match(g="v2")]
    assert q.must_not == [query.Match(title='value')]
Ejemplo n.º 13
0
def test_bool_queries_with_only_should_get_concatenated():
    q1 = query.Bool(should=[query.Match(f=1), query.Match(f=2)])
    q2 = query.Bool(should=[query.Match(f=3), query.Match(f=4)])

    assert (q1 | q2) == query.Bool(
        should=[query.Match(f=1), query.Match(f=2), query.Match(f=3), query.Match(f=4)]
    )
Ejemplo n.º 14
0
def departments_query(search_term: str) -> Q.Query:
    """
    Returns the ONS departments query
    :param search_term:
    :return:
    """
    return Q.Match(**{"terms": {"query": search_term, "type": "boolean"}})
Ejemplo n.º 15
0
def test_other_and_bool_appends_other_to_must():
    q1 = query.Match(f='value1')
    qb = query.Bool()

    q = q1 & qb
    assert q is not qb
    assert q.must[0] == q1
Ejemplo n.º 16
0
def test_match_to_dict_extra():
    assert {
        "match": {
            "f": "value",
            "boost": 2
        }
    } == query.Match(f='value', boost=2).to_dict()
Ejemplo n.º 17
0
def test_bool_and_other_appends_other_to_must():
    q1 = query.Match(f="value1")
    qb = query.Bool()

    q = qb & q1
    assert q is not qb
    assert q.must[0] == q1
Ejemplo n.º 18
0
    def primary_should_rules(self, search_query, analyzer):
        """Return "primary" should rules for the query.

        These are the ones using the strongest boosts, so they are only applied
        to a specific set of fields like the name, the slug and authors.

        Applied rules:

        * Prefer phrase matches that allows swapped terms (boost=4)
        * Then text matches, using the standard text analyzer (boost=3)
        * Then text matches, using a language specific analyzer (boost=2.5)
        * Then try fuzzy matches ("fire bug" => firebug) (boost=2)
        * Then look for the query as a prefix of a name (boost=1.5)
        """
        should = []
        rules = [
            (query.MatchPhrase, {
                'query': search_query, 'boost': 4, 'slop': 1}),
            (query.Match, {
                'query': search_query, 'boost': 3,
                'analyzer': 'standard'}),
            (query.Match, {
                'query': search_query, 'boost': 2,
                'prefix_length': 4, 'fuzziness': 'AUTO'}),
            (query.Prefix, {
                'value': search_query, 'boost': 1.5}),
        ]

        # Apply rules to search on few base fields. Some might not be present
        # in every document type / indexes.
        for query_cls, opts in rules:
            for field in ('name', 'slug', 'listed_authors.name'):
                should.append(query_cls(**{field: opts}))

        # Exact matches need to be queried against a non-analyzed field. Let's
        # do a term query on `name.raw` for an exact match against the add-on
        # name and boost it since this is likely what the user wants.
        # Use a super-high boost to avoid `description` or `summary`
        # getting in our way.
        should.append(query.Term(**{
            'name.raw': {
                'value': search_query, 'boost': 100
            }
        }))

        # For name, also search in translated field with the right language
        # and analyzer.
        if analyzer:
            should.append(
                query.Match(**{
                    'name_l10n_%s' % analyzer: {
                        'query': search_query,
                        'boost': 2.5,
                        'analyzer': analyzer
                    }
                })
            )

        return should
Ejemplo n.º 19
0
def test_bool_and_other_appends_other_to_must():
    q1 = query.Match(f='value1')
    qb = query.Bool()

    q = qb & q1
    print(repr(q))
    assert q is not qb
    assert q.must[0] == q1
Ejemplo n.º 20
0
def search_author(request):
    """
    returns a list of authors depending on the search query

    request needs to have 'query':str field
    """

    query = request.query_params.get('query', None)
    if query is None:
        return http.HttpResponseBadRequest('no query supplied.')

    pagesize = request.query_params.get('pagesize', '40')
    if not pagesize.isnumeric() or int(pagesize) < 1:
        return http.HttpResponseBadRequest('invalid page size.')
    pagesize = int(pagesize)

    name_query = dsl_query.Match(name={'query': query})
    result = AuthorDocument.search().query(name_query)

    search_result = Author.objects.filter(name__icontains=query)

    count = result.count()

    if count <= 0:
        return http.JsonResponse(
            {
                'data': PaperSerializer([], many=True).data,
                'max_pages': 0,
                'count': 0
            },
            safe=False)

    max_pages = min((count - 1) // pagesize + 1,
                    (SEARCH_CAP - 1) // pagesize + 1)
    count = min(count, SEARCH_CAP)
    # Limit as elasticsearch has a limit on slices. This can be extended in the future
    # Example for error:
    # - Remove max(...,SEARCH_CAP) in expression above
    # - Search for Gao in Authors
    # - All Results above result 10.0000 should fail to load

    page = request.query_params.get('page', '1')
    if not page.isnumeric() or int(page) > max_pages:
        return http.HttpResponseBadRequest('invalid page number.')
    page = int(page)

    return http.JsonResponse(
        {
            'data':
            AuthorSerializer(result[pagesize *
                                    (page - 1):pagesize * page].to_queryset(),
                             many=True).data,
            'max_pages':
            max_pages,
            'count':
            count,
        },
        safe=False)
Ejemplo n.º 21
0
    def primary_should_rules(self, search_query, analyzer):
        """Return "primary" should rules for the query.

        These are the ones using the strongest boosts, so they are only applied
        to a specific set of fields like the name, the slug and authors.

        Applied rules:

        * Prefer phrase matches that allows swapped terms (boost=4)
        * Then text matches, using the standard text analyzer (boost=3)
        * Then text matches, using a language specific analyzer (boost=2.5)
        * Then try fuzzy matches ("fire bug" => firebug) (boost=2)
        * Then look for the query as a prefix of a name (boost=1.5)
        """
        should = []
        rules = [
            (query.MatchPhrase, {
                'query': search_query,
                'boost': 4,
                'slop': 1
            }),
            (query.Match, {
                'query': search_query,
                'boost': 3,
                'analyzer': 'standard'
            }),
            (query.Fuzzy, {
                'value': search_query,
                'boost': 2,
                'prefix_length': 4
            }),
            (query.Prefix, {
                'value': search_query,
                'boost': 1.5
            }),
        ]

        # Apply rules to search on few base fields. Some might not be present
        # in every document type / indexes.
        for k, v in rules:
            for field in ('name', 'slug', 'listed_authors.name'):
                should.append(k(**{field: v}))

        # For name, also search in translated field with the right language
        # and analyzer.
        if analyzer:
            should.append(
                query.Match(
                    **{
                        'name_l10n_%s' % analyzer: {
                            'query': search_query,
                            'boost': 2.5,
                            'analyzer': analyzer
                        }
                    }))

        return should
Ejemplo n.º 22
0
def test_bool_from_dict_issue_318():
    d = {
        "bool": {
            "must_not": {"match": {"field": "value"}}
        }
    }
    q = query.Q(d)

    assert q == ~query.Match(field='value')
Ejemplo n.º 23
0
def match_by_uri(uri: str) -> Q.Query:
    """
    Match a document by its uri
    :param uri:
    :return:
    """
    if not uri.startswith("/"):
        uri = "/" + uri
    return Q.Match(_id=uri)
Ejemplo n.º 24
0
    def secondary_should_rules(self, search_query, analyzer):
        """Return "secondary" should rules for the query.

        These are the ones using the weakest boosts, they are applied to fields
        containing more text like description, summary and tags.

        Applied rules:

        * Look for phrase matches inside the summary (boost=0.8)
        * Look for phrase matches inside the summary using language specific
          analyzer (boost=0.6)
        * Look for phrase matches inside the description (boost=0.3).
        * Look for phrase matches inside the description using language
          specific analyzer (boost=0.1).
        * Look for matches inside tags (boost=0.1).
        """
        should = [
            query.MatchPhrase(summary={
                'query': search_query,
                'boost': 0.8
            }),
            query.MatchPhrase(description={
                'query': search_query,
                'boost': 0.3
            }),
        ]

        # Append a separate 'match' query for every word to boost tag matches
        for tag in search_query.split():
            should.append(query.Match(tags={'query': tag, 'boost': 0.1}))

        # For description and summary, also search in translated field with the
        # right language and analyzer.
        if analyzer:
            should.extend([
                query.MatchPhrase(
                    **{
                        'summary_l10n_%s' % analyzer: {
                            'query': search_query,
                            'boost': 0.6,
                            'analyzer': analyzer
                        }
                    }),
                query.MatchPhrase(
                    **{
                        'description_l10n_%s' % analyzer: {
                            'query': search_query,
                            'boost': 0.6,
                            'analyzer': analyzer
                        }
                    })
            ])

        return should
Ejemplo n.º 25
0
    def primary_should_rules(self, search_query, analyzer):
        """Return "primary" should rules for the query.

        These are the ones using the strongest boosts, so they are only applied
        to a specific set of fields like the name, the slug and authors.
        """
        should = []
        rules = [
            (query.Match, {
                'query': search_query,
                'boost': 3,
                'analyzer': 'standard'
            }),
            (query.Match, {
                'query': search_query,
                'boost': 4,
                'type': 'phrase',
                'slop': 1
            }),
            (query.Prefix, {
                'value': search_query,
                'boost': 1.5
            }),
        ]

        # Only add fuzzy queries if the search query is a single word.
        # It doesn't make sense to do a fuzzy query for multi-word queries.
        if ' ' not in search_query:
            rules.append((query.Fuzzy, {
                'value': search_query,
                'boost': 2,
                'prefix_length': 4
            }))

        # Apply rules to search on few base fields. Some might not be present
        # in every document type / indexes.
        for k, v in rules:
            for field in ('name', 'slug', 'authors'):
                should.append(k(**{field: v}))

        # For name, also search in translated field with the right language
        # and analyzer.
        if analyzer:
            should.append(
                query.Match(
                    **{
                        'name_%s' % analyzer: {
                            'query': search_query,
                            'boost': 2.5,
                            'analyzer': analyzer
                        }
                    }))

        return should
Ejemplo n.º 26
0
def test_Q_constructs_compound_query_from_dict():
    q = query.Q({"bool": {
        "must": [
            {
                'match': {
                    'f': 'value'
                }
            },
        ]
    }})

    assert q == query.Bool(must=[query.Match(f='value')])
Ejemplo n.º 27
0
def match(field, search_term, **kwargs):
    field_name = _get_field_name(field)

    query_dict = {
        field_name: {
            "query": search_term,
        }
    }

    for item in kwargs:
        query_dict[field_name][item] = kwargs[item]

    q = query.Match(**query_dict)
    return q
Ejemplo n.º 28
0
def build_match_query(key: str,
                      term: str,
                      fuzziness: str,
                      boost_factor: int = 1) -> query.Query:
    return query.Match(
        **{
            key: {
                'query': term,
                'operator': 'or',
                "fuzziness": fuzziness,
                "minimum_should_match": "3<75%",
                'boost': boost_factor
            }
        })
Ejemplo n.º 29
0
def test_allow_multiple_queries_for_constant_score_issue_599():
    # Construct a number of ConstantScore queries each with different
    # combinations of queries and filters.
    q1 = query.ConstantScore(query=[query.Match(f=1), query.Match(f=2)])
    q2 = query.ConstantScore(filter=[query.Match(f=1), query.Match(f=2)])
    q3 = query.ConstantScore(query=query.Match(f=1))
    q4 = query.ConstantScore(filter=query.Match(f=1))

    for q in [q1, q2, q3, q4]:
        assert isinstance(q.to_dict(), dict)
Ejemplo n.º 30
0
def test_two_bool_queries_append_one_to_should_if_possible():
    q1 = query.Bool(should=[query.Match(f='v')])
    q2 = query.Bool(must=[query.Match(f='v')])

    assert (q1 | q2) == query.Bool(
        should=[query.Match(
            f='v'), query.Bool(must=[query.Match(f='v')])])
    assert (q2 | q1) == query.Bool(
        should=[query.Match(
            f='v'), query.Bool(must=[query.Match(f='v')])])