我试图在ElasticSearch中编写一个查询,该查询匹配单词中的连续字符。因此,如果我的索引包含“ John Doe”,则对于以下搜索,我仍然应该看到Elasticsearch返回的“ John Doe”。
到目前为止,我已经尝试了以下查询。
{
"query": {
"multi_match": {
"query": "term",
"operator": "OR",
"type": "phrase_prefix",
"max_expansions": 50,
"fields": [
"Field1",
"Field2"
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
但这也会返回不必要的匹配,例如当我键入john x时我仍然会得到“ John Doe”。
正如我在上面的评论中所解释的那样,随着索引的增长,应该不惜一切代价避免使用前缀通配符,因为这将迫使ES进行完整的索引扫描。我仍然坚信ngrams(更确切地说是edge-ngrams)是要走的路,因此我在下面对此进行了介绍。
这个想法是索引输入的所有后缀,然后使用prefix查询来匹配任何后缀,因为搜索前缀不会遇到与搜索后缀相同的性能问题。因此,想法是索引john doe如下:
john doe
ohn doe
hn doe
n doe
doe
oe
e
Run Code Online (Sandbox Code Playgroud)
这样,使用prefix查询,我们可以匹配这些标记的任何子部分,从而有效地实现匹配部分连续单词的目标,同时确保良好的性能。
索引的定义如下:
PUT my_index
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": [
"lowercase",
"reverse",
"suffixes",
"reverse"
]
}
},
"filter": {
"suffixes": {
"type": "edgeNGram",
"min_gram": 1,
"max_gram": 20
}
}
}
}
},
"mappings": {
"doc": {
"properties": {
"name": {
"type": "text",
"analyzer": "my_analyzer",
"search_analyzer": "standard"
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以为样本文档建立索引:
PUT my_index/doc/1
{
"name": "john doe"
}
Run Code Online (Sandbox Code Playgroud)
最后,以下所有搜索将返回john doe文档:
POST my_index/_search
{
"query": {
"prefix": {
"name": "john doe"
}
}
}
POST my_index/_search
{
"query": {
"prefix": {
"name": "john do"
}
}
}
POST my_index/_search
{
"query": {
"prefix": {
"name": "ohn do"
}
}
}
POST my_index/_search
{
"query": {
"prefix": {
"name": "john"
}
}
}
POST my_index/_search
{
"query": {
"prefix": {
"name": "n doe"
}
}
}
Run Code Online (Sandbox Code Playgroud)
这对我有用。将数据作为关键字索引,而不是 ngram。并使用通配符正则表达式匹配来匹配单词。
"query": {
"bool": {
"should": [
{
"wildcard": { "Field1": "*" + term + "*" }
},
{
"wildcard": { "Field2": "*" + term + "*" }
}
],
"minimum_should_match": 1
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1135 次 |
| 最近记录: |