示例#1
0
def autocomplete_search(q, doc_type=None, fuzzy_mode=False, **kwargs):

    query = autocomplete_query(q, fuzzy_mode)
    limit = kwargs.get('limit', 20)
    offset = kwargs.get('offset', 0)
    filters = kwargs.get('filters', {})

    if limit and limit > 100:
        limit = 100

    s = Search().index('_all')

    if doc_type:
        s = s.doc_type(doc_type)

    s = s.query('match', autocomplete=query)

    # TODO: implement in a generic way
    # add filters like: `&filter_status=Ready&filter_type=Broadcasts`
    for key, value in filters.iteritems():
        s = s.query('term', **{key: value[0]})

    s = s[offset:limit + offset]

    return format_search_results(s.execute())
def autocomplete(query: str) -> Response:
    """
    https://www.elastic.co/guide/en/elasticsearch/guide/current/_index_time_search_as_you_type.html
    We use the ngram-based autocomplete-analyzer for indexing, but the standard analyzer for searching
    This way we enforce that the whole entered word has to be matched (save for some fuzziness) and the algorithm
    does not fall back to matching only the first character in extreme cases. This prevents absurd cases where
    "Garret Walker" and "Hector Mendoza" are suggested when we're entering "Mahatma Ghandi"
    """
    search_query = Search(index=list(DOCUMENT_INDICES.values()))
    search_query = search_query.query(
        "match",
        autocomplete={
            "query": escape_elasticsearch_query(query),
            "analyzer": "standard",
            "fuzziness": "AUTO",
            "prefix_length": 1,
        },
    )
    search_query = search_query.extra(min_score=1)
    search_query = search_query.update_from_dict({
        "indices_boost": [
            {
                DOCUMENT_INDICES["person"]: 4
            },
            {
                DOCUMENT_INDICES["organization"]: 4
            },
            {
                DOCUMENT_INDICES["paper"]: 2
            },
        ]
    })
    response = search_query.execute()
    return response
 def query(self, search: Search, query: str) -> Search:
     if query:
         self.options["searchterm"] = query
         # Fuzzines AUTO(=2) gives more error tolerance, but is also a lot slower and has many false positives
         # We're using https://stackoverflow.com/a/35375562/3549270 to make exact matches score higher than fuzzy
         # matches
         search = search.query(
             Bool(should=[
                 MultiMatch(
                     query=escape_elasticsearch_query(query),
                     operator="and",
                     fields=self.fields,
                 ),
                 MultiMatch(
                     query=escape_elasticsearch_query(query),
                     operator="and",
                     fields=self.fields,
                     fuzziness="1",
                     prefix_length=1,
                 ),
             ]))
     return search