如何用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* 

诀窍!