代码之家  ›  专栏  ›  技术社区  ›  gtalarico

弹性搜索建议返回零结果

  •  0
  • gtalarico  · 技术社区  · 6 年前

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

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

    我对弹性很陌生,所以我想我错过了一些东西。 任何指导都将不胜感激!

    我到目前为止所做的

    我没有找到一个完全符合我要求的教程,但是我在elasticsearch.com上阅读了文档,并且 elasticsearch_dsl 并看了一些例子 here here

    我在Heroku上使用搜索框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'
    

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

    核实 标题\建议 正在正确索引

    >>> 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"
              }
            }
          }
        }
      }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Honza Král    6 年前

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

        2
  •  0
  •   gtalarico    6 年前

    我想将本扎对另一个答案的评论提供的解决方案形式化。

    问题不在于地图,而在于 .suggest() 方法不在下返回 hits .

    建议现在可以在字典中看到,返回者为:

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

    我还找到了更多关于这个的细节 github issue :

    洪扎克雷27天前评论道

    响应对象提供对 由ElasticSearch返回。为了方便,有一条捷径 它允许对点击进行迭代,因为这是最常见的和 也很容易做到。 对于响应的其他部分,如聚合或 建议,你需要像 response.suggest.foo.选项。