【问题标题】:Elastic Search Suggestions Return Zero Results弹性搜索建议返回零结果
【发布时间】:2018-07-26 07:19:14
【问题描述】:

我正在尝试使用 elasticsearch_dsl python 库设置 ElasticSearch。我已经能够设置索引,并且可以使用.filter() 方法进行搜索,但我无法让.suggest 方法工作。

我正在尝试使用 completion 映射类型和 suggest 查询方法,因为这将用于自动完成字段(在 elastic 的文档中推荐)。

我是弹性新手,所以我猜我错过了一些东西。 任何指导将不胜感激!

到目前为止我做了什么

我没有找到完全符合我要求的教程,但我阅读了 ElasticSearch.com 和 elasticsearch_dsl 上的文档,并查看了一些示例 herehere

PS:我在 Heroku 上使用 Searchbox Elasticsearch

索引/映射设置:

# imports [...]

edge_ngram_analyzer = analyzer(
    'edge_ngram_analyzer',
    type='custom',
    tokenizer='standard',
    filter=[
        'lowercase',
        token_filter(
            'edge_ngram_filter', type='edgeNGram',
            min_gram=1, max_gram=20
        )
    ]
)

class DocumentIndex(ElasticDocument):
    title = Text()
    title_suggest = Completion(
        analyzer=edge_ngram_analyzer,
        )
    class Index:
        name = 'documents-index'

# [...] Initialize index
# [...] Upload Documents (5,000 documents)
# DocumentIndex.init()
# [DocumentIndex(**doc).save() for doc in mydocs]

映射输出:

这是 web 控制台中显示的映射:

 {
  "documents-index": {
    "mappings": {
      "doc": {
        "properties": {
          "title": {
            "type": "text"
          },
          "title_suggest": {
            "type": "completion",
            "analyzer": "edge_ngram_analyzer",
            "search_analyzer": "standard",
            "preserve_separators": true,
            "preserve_position_increments": true,
            "max_input_length": 50
          }
        }
      }
    }
  }
}

尝试搜索

验证索引是否存在:

>>> search = Search(index='documents-index')
>>> search.count()  # Returns correct amount of documents
5000
>>> [doc for doc in search.scan()][:3]
>>> [<Hit(documents-index/doc/1): ...} ...

测试搜索 - 作品:

>>> query = search.filter('match', title='class')
>>> query.execute()
>>> result.hits 
<Response: [<Hit(documents-in [ ... ]
>>> len(result.hits)
10
>>> query.to_dict()  # see query payload
{ 
  "query":{
    "bool":{
      "filter":[
        {
          "fuzzy":{
            "title":"class"
          }
        }
      ]
    }
  }
}

失败的部分

我无法使用任何.suggest() 方法。 笔记: * 我在关注官方library docs

测试建议:

>>> query = search.suggest(
        'title-suggestions',
        'class',
        completion={
        'field': 'title_suggest',
        'fuzzy': True
        })
>>> query.execute()
<Response: {}>
>>> query.to_dict() # see query payload
{
  "suggest": {
    "title-suggestions": {
      "text": "class",
      "completion": { "field": "title_suggest" }
    }
  }
}

我也尝试了下面的代码,显然有很多不同类型的查询和值,但结果是相似的。 (注意.filter() 我总是得到预期的结果)。

>>> query = search.suggest(
        'title-suggestions',
        'class',
         term=dict(field='title'))
>>> query.to_dict() # see query payload
{
  "suggest": {
    "title-suggestions": { 
        "text": "class", 
        "term": { 
            "field": "title" 
        } 
    }
  }
}
>>> query.execute()
<Response: {}>

更新

根据 Honza 的建议,我将 title_suggest 映射更新为仅完成,没有自定义分析器。我还删除了索引并从头开始重新索引

class DocumentIndex(ElasticDocument):
    title = Text()
    title_suggest = Completion()
    class Index:
        name = 'documents-index'

不幸的是,问题仍然存在。这里还有一些测试:

验证 title_suggest 是否被正确编入索引

>>> search = Search(index='documents-index)
>>> search.index('documents-index').count()
23369
>>> [d for d in search.scan()][0].title
'AnalyticalGrid Property'
>>> [d for d in search.scan()][0].title_suggest
'AnalyticalGrid Property'

再次尝试搜索:

>>> len(search.filter('term', title='class').execute().hits)
10
>>> search.filter('term', title_suggest='Class').execute().hits
[]
>>> search.suggest('suggestions', 'class', completion={'field': 
'title_suggest'}).execute().hits
[]

验证映射:

>>> pprint(index.get_mapping())
{
  "documents-index": {
    "mappings": {
      "doc": {
        "properties": {
          "title": { "type": "text" },
          "title_suggest": {
            "analyzer": "simple",
            "max_input_length": 50,
            "preserve_position_increments": True,
            "preserve_separators": True,
            "type": "completion"
          }
        }
      }
    }
  }
}

【问题讨论】:

    标签: elasticsearch elasticsearch-dsl elasticsearch-dsl-py


    【解决方案1】:

    对于完成字段,您不想使用ngram 分析器。 completion 字段将自动为所有前缀编制索引并针对前缀查询进行优化,因此您需要进行两次工作并混淆系统。从空的 completion 字段开始,然后从那里开始。

    【讨论】:

    • 感谢 Honza 的建议 - 我在图书馆的 github 上看到了很多你的回复,所以很高兴在这里见到你。感谢您为这个项目所做的所有工作。
    • 我已经用你的建议更新了这个问题,但是它并没有解决问题。
    • 建议不会以hits 的形式返回,您需要检查您返回的响应,尤其是.suggestions 属性。我建议只是四处看看,也许看看response.to_dict() 看看有什么可用
    • 再次感谢您的建议。我会试试这个
    【解决方案2】:

    我想将 Honza 在其中一个 cmets 上提供的解决方案形式化,以获得另一个答案。

    问题不在于映射,而仅仅是由于 在hits 下不返回.suggest() 方法。

    这些建议现在在以下人返回的字典中可见:

    >>> response = query.execute()
    >>> print(response)
    <Response: {}>
    >>> response.to_dict()
    # output is
    # {'query': {},
    # 'suggest': {'title-suggestions': {'completion': {'field': 'title_suggest'},
    # [...]
    

    我还找到了有关此github issue 的更多详细信息:

    HonzaKral 于 27 天前发表评论

    Response 对象提供对任何和所有具有 由弹性搜索返回。为方便起见,有一条捷径 允许迭代命中,因为这既是最常见的,也是 也很容易做到。 对于响应的其他部分,例如聚合或 建议,您需要像这样明确地访问它们 response.suggest.foo.options.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-10
      • 1970-01-01
      • 2016-12-09
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-20
      • 1970-01-01
      相关资源
      最近更新 更多