首页 > 解决方案 > Elasticsearch 短语/多世界搜索

问题描述

我正在尝试实现一个用例,其中用户可以对“product_name”字段进行多词/短语搜索。

假设有人在搜索“最富有的人”,应该会出现以下结果:

搜索结果不得包含以下文档 -

这是我写的分析器:

'settings' => [
    'analysis' => [
        'filter' => [
            'autocomplete_filter' => ['type' => 'ngram', 'min_gram' => 1, 'max_gram' => 10]
        ],
        'analyzer' => [
            'autocomplete' => ['type' => 'custom', 'tokenizer' => 'standard', 'filter' => ['lowercase', 'autocomplete_filter']]
        ]
    ],
    'index.max_ngram_diff' => 10
],
'mappings' => ['properties' => [
    'product_name' => ['type' => 'text', 'analyzer' => 'autocomplete', 'search_analyzer', 'standard'],                  
]],

我正在使用以下用 PHP 编写的代码来发出搜索请求:

$params = [
    'index' => ProductData::ELASTIC_INDEX,
    'type' => ProductData::ELASTIC_TYPE,
    'body' => [
        'query' => ['match' => ['product_name' => ['query' => $requestVars['product_name']]]
    ],
    ]
];

$result =  $this->client->search($params);

但是,我得到的结果是出乎意料的,而不是我上面列出的结果。

标签: phpelasticsearchsearch

解决方案


由于您已经定义了autocomplete分析器,其中有一个 n-gram 标记器,因此生成的标记"When a poor man becomes the richest"将包括"when", "a", "poor", "man", "becomes", "the", "richest"

现在,当您搜索 时,这将返回所有在其文档中具有或Richest Man的匹配文档richestman

您可以简单地使用match_phrase 查询,而不是定义任何单独的分析器

添加一个工作示例

索引映射:

{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      }
    }
  }
}

搜索查询:

{
  "query": {
    "match_phrase": {
      "name": "Richest Man"
    }
  }
}

搜索结果将是

"hits": [
      {
        "_index": "67784465",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.15394104,
        "_source": {
          "name": "The Richest Man in Babylon"
        }
      },
      {
        "_index": "67784465",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.15394104,
        "_source": {
          "name": "Story of the Richest man"
        }
      },
      {
        "_index": "67784465",
        "_type": "_doc",
        "_id": "3",
        "_score": 0.14290144,
        "_source": {
          "name": "The richest man in the world"
        }
      },
      {
        "_index": "67784465",
        "_type": "_doc",
        "_id": "4",
        "_score": 0.14290144,
        "_source": {
          "name": "How to win the richest man"
        }
      }
    ]

推荐阅读