我最近开始使用ElasticSearch,我似乎无法让它搜索一个单词的一部分 .
示例:我在我的couchdb中有三个索引在ElasticSearch中索引的文档:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
所以现在,我想搜索包含“Doe”的所有文件
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
这不会返回任何命中 . 但是,如果我搜索
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
它确实返回一个文件(John Doeman) .
我尝试过设置不同的分析器和不同的过滤器作为索引的属性 . 我也试过使用完整的查询(例如:
{
"query": {
"term": {
"name": "Doe"
}
}
}
但似乎没有任何作用 .
当我搜索“Doe”时,如何让ElasticSearch找到John Doeman和Jane Doewoman?
UPDATE
我尝试使用nGram标记器和过滤器,就像Igor提出的那样,如下所示:
{
"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文档并不是很好......
9 回答
我也在使用nGram . 我使用标准tokenizer和nGram作为过滤器 . 这是我的设置:
让我们找到最多50个字母的单词部分 . 根据需要调整max_gram . 在德语中,单词可以变得非常大,所以我将其设置为高 Value .
使用前导和尾随通配符进行搜索对于大型索引来说会非常慢 . 如果您希望能够通过单词前缀进行搜索,请删除前导通配符 . 如果你真的需要在一个单词的中间找到一个子字符串,那么你最好使用ngram tokenizer .
我认为没有必要改变任何映射 . 尝试使用 query_string ,它是完美的 . 所有方案都适用于默认的标准分析器:
我们有数据:
Scenario 1:
响应:
Scenario 2:
响应:
Scenario 3:
响应:
编辑 - 与 spring 数据弹性搜索相同的实现https://stackoverflow.com/a/43579948/2357869
再解释一下query_string如何比其他更好https://stackoverflow.com/a/43321606/2357869
在不更改索引映射的情况下,您可以执行简单的前缀查询,该查询将执行您希望的部分搜索
即 .
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
尝试使用此处描述的解决方案:Exact Substring Searches in ElasticSearch
要解决磁盘使用问题和过长的搜索项问题,请使用短8个字符长的ngram(配置为:"max_gram":8) . 要搜索超过8个字符的术语,请将搜索转换为布尔AND查询,以查找该字符串中每个不同的8个字符的子字符串 . 例如,如果用户搜索大码(10个字符的字符串),搜索将是:
“arge ya和arge yar and rge yard .
如果要实现自动完成功能,那么Completion Suggester是最简洁的解决方案 . 下一个blog post包含一个非常清晰的描述如何工作 .
换句话说,它是一个称为FST的内存数据结构,它包含有效的建议,并针对快速检索和内存使用进行了优化 . 从本质上讲,它只是一个图表 . 例如,包含单词
hotel
,marriot
,mercure
,munchen
和munich
的FST将如下所示:Elasticsearch具有通配符查询,可以在这种情况下使用,并且是最简单的查询 . 它将返回两个匹配的文档
你可以使用正则表达式 .
如果您使用此查询:
你将给出他们的名字以“J”开头的所有数据 . 考虑你只想接收他们的名字以“man”结尾的前两个记录,这样你就可以使用这个查询:
如果你想接收名字中存在“m”的所有记录,你可以使用这个查询:
这对我有用 . 我希望我的答案适合解决你的问题 .
没关系 .
我不得不看看Lucene的文档 . 似乎我可以使用通配符! :-)
诀窍!