如何用ElasticSearchsearch单词的一部分
我最近开始使用ElasticSearch,似乎无法使其search单词的一部分。
例如:我在ElasticSearch中索引了三个来自我的couchdb的文档:
{ "_id" : "1", "name" : "John Doeman", "function" : "Janitor" } { "_id" : "2", "name" : "Jane Doewoman", "function" : "Teacher" } { "_id" : "3", "name" : "Jimmy Jackal", "function" : "Student" }
所以现在我想search所有包含“Doe”的文件
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
这不会返回任何命中。 但是,如果我search
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
它确实会返回一个文件(John Doeman)。
我已经尝试将不同的分析器和不同的filter设置为我的索引的属性。 我也尝试使用一个完整的查询(例如:
{ "query": { "term": { "name": "Doe" } } }
)但似乎没有任何工作。
当我search“Doe”时,如何让ElasticSearchfindJohn Doeman和Jane Doewoman?
UPDATE
我试图使用nGram标记器和filter,就像伊戈尔提出的,像这样:
{ "index": { "index": "my_idx", "type": "my_type", "bulk_size": "100", "bulk_timeout": "10ms", "analysis": { "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "my_ngram_tokenizer", "filter": [ "my_ngram_filter" ] } }, "filter": { "my_ngram_filter": { "type": "nGram", "min_gram": 1, "max_gram": 1 } }, "tokenizer": { "my_ngram_tokenizer": { "type": "nGram", "min_gram": 1, "max_gram": 1 } } } } }
我现在遇到的问题是,每个查询返回所有文档。 任何指针? 有关使用nGram的ElasticSearch文档不是很好…
我也使用nGram。 我使用标准的tokenizer和nGram只是一个filter。 这是我的设置:
{ "index": { "index": "my_idx", "type": "my_type", "analysis": { "index_analyzer": { "my_index_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "mynGram" ] } }, "search_analyzer": { "my_search_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "standard", "lowercase", "mynGram" ] } }, "filter": { "mynGram": { "type": "nGram", "min_gram": 2, "max_gram": 50 } } } } }
让我们find多达50个字母的单词部分。 根据需要调整max_gram。 在德国的话可以变得非常大,所以我把它设置得很高。
在一个大的索引上search前导和尾随通配符将会非常缓慢。 如果您希望能够使用字词前缀进行search,请删除前导通配符。 如果你确实需要在一个词的中间find一个子string,那么使用ngram tokenizer会更好。
我认为没有必要改变任何映射。 尝试使用query_string ,这是完美的。 所有场景都可以使用默认的标准分析仪:
我们有数据:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"} {"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
情况1:
{"query": { "query_string" : {"default_field" : "name", "query" : "*Doe*"} } }
响应:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"} {"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
情景2:
{"query": { "query_string" : {"default_field" : "name", "query" : "*Jan*"} } }
响应:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
情景3:
{"query": { "query_string" : {"default_field" : "name", "query" : "*oh* *oe*"} } }
响应:
{"_id" : "1","name" : "John Doeman","function" : "Janitor"} {"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}
编辑 – 与弹簧数据弹性search相同的实现https://stackoverflow.com/a/43579948/2357869
多一个解释如何query_string比其他人更好https://stackoverflow.com/a/43321606/2357869
在不改变你的索引映射的情况下,你可以做一个简单的前缀查询来完成你所希望的部分search
即。
{ "query": { "prefix" : { "name" : "Doe" } } }
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
试用解决scheme,在这里描述: ElasticSearch中的精确子串search
{ "mappings": { "my_type": { "index_analyzer":"index_ngram", "search_analyzer":"search_ngram" } }, "settings": { "analysis": { "filter": { "ngram_filter": { "type": "ngram", "min_gram": 3, "max_gram": 8 } }, "analyzer": { "index_ngram": { "type": "custom", "tokenizer": "keyword", "filter": [ "ngram_filter", "lowercase" ] }, "search_ngram": { "type": "custom", "tokenizer": "keyword", "filter": "lowercase" } } } } }
为了解决磁盘使用问题和长达8个字符长的search词问题(使用“max_gram”:8configuration),使用了太长的search词问题。 要search超过8个字符的字词,请将search转换为布尔AND查询,以查找该string中每个不同的8字符子string。 例如,如果用户search大码 (10个字符的string),search将是:
“大声说道:
Elasticsearch有通配符查询可以在这种情况下使用,是最简单的。 它将返回两个匹配的文档
没关系。
我不得不看看Lucene的文档。 似乎我可以使用通配符! 🙂
curl http://localhost:9200/my_idx/my_type/_search?q=*Doe*
诀窍!