我有此数据:
name: first: 'John' last: 'Smith'
当我将其存储在ES,AFAICT中时,最好使其成为一个字段。但是,此字段应为:
name: 'John Smith'
要么
name: 'JohnSmith'
?
我认为查询应该是:
query: match: name: query: searchTerm fuzziness: 'AUTO' operator: 'and'
人们可能会在搜索框中输入搜索字词示例,例如
John Jhon Smi J Smith Smith
等等
您可能需要结合使用ngram和模糊匹配查询。如果您需要入门,我写了一篇有关Qbox的ngram的博客文章:https ://qbox.io/blog/an-introduction-to- ngrams-in-elasticsearch 。我将在帖子结尾处滑动入门代码,以说明我的意思。
另外,我认为您是使用两个字段name还是仅使用一个字段都没有多大关系。如果由于其他原因需要两个字段,则可能要在查询中使用该_all字段。为简单起见,我在这里只使用一个字段。
name
_all
这是一个映射,可以让您获得想要的部分单词匹配,假设您只在乎单词开头的标记(否则使用ngrams而不是edge ngrams)。使用ngram有很多细微差别,因此如果您需要更多信息,我将参考您的文档和入门。
PUT /test_index { "settings": { "number_of_shards": 1, "analysis": { "filter": { "edge_ngram_filter": { "type": "edge_ngram", "min_gram": 1, "max_gram": 10 } }, "analyzer": { "edge_ngram_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "edge_ngram_filter" ] } } } }, "mappings": { "doc": { "properties": { "name": { "type": "string", "index_analyzer": "edge_ngram_analyzer", "search_analyzer": "standard" } } } } }
这里要特别注意的一件事:"min_gram": 1。这意味着将从索引值生成单字符令牌。当您查询时,这将产生一个相当宽的网络(例如,许多单词以“ j”开头),因此您可能会得到一些意外的结果,尤其是在与模糊性结合时。但这是使您的“ J Smith”查询正常运行所必需的。因此,需要权衡取舍。
"min_gram": 1
为了说明,我索引了四个文档:
PUT /test_index/doc/_bulk {"index":{"_id":1}} {"name":"John Hancock"} {"index":{"_id":2}} {"name":"John Smith"} {"index":{"_id":3}} {"name":"Bob Smith"} {"index":{"_id":4}} {"name":"Bob Jones"}
您的查询通常有效,但有几点警告。
POST /test_index/_search { "query": { "match": { "name": { "query": "John", "fuzziness": "AUTO", "operator": "and" } } } }
由于ngrams加上模糊性,此查询返回三个文档:
{ "took": 3, "timed_out": false, "_shards": { "total": 1, "successful": 1, "failed": 0 }, "hits": { "total": 3, "max_score": 0.90169895, "hits": [ { "_index": "test_index", "_type": "doc", "_id": "1", "_score": 0.90169895, "_source": { "name": "John Hancock" } }, { "_index": "test_index", "_type": "doc", "_id": "2", "_score": 0.90169895, "_source": { "name": "John Smith" } }, { "_index": "test_index", "_type": "doc", "_id": "4", "_score": 0.6235822, "_source": { "name": "Bob Jones" } } ] } }
那可能不是您想要的。另外,"AUTO"不适用于“ Jhon Smi”查询,因为“ Jhon”与“ John”的编辑距离为2,而“ AUTO”对3-5个字符的字符串使用的编辑距离为1(请参阅文档有关更多信息)。因此,我必须改用以下查询:
"AUTO"
POST /test_index/_search { "query": { "match": { "name": { "query": "Jhon Smi", "fuzziness": 2, "operator": "and" } } } } ... { "took": 17, "timed_out": false, "_shards": { "total": 1, "successful": 1, "failed": 0 }, "hits": { "total": 1, "max_score": 1.4219328, "hits": [ { "_index": "test_index", "_type": "doc", "_id": "2", "_score": 1.4219328, "_source": { "name": "John Smith" } } ] } }
其他查询按预期方式工作。因此,该解决方案并不完美,但是它将使您接近。
这是我使用的所有代码:
http://sense.qbox.io/gist/ba5a6741090fd40c1bb20f5d36f3513b4b55ac77