我正在尝试在ElasticSearch中编写一个查询,该查询匹配单词中的连续字符。所以,如果我的索引有" John Doe",我仍然应该看到" John Doe" Elasticsearch为以下搜索返回。
到目前为止,我已尝试过以下查询。
{
"query": {
"multi_match": {
"query": "term",
"operator": "OR",
"type": "phrase_prefix",
"max_expansions": 50,
"fields": [
"Field1",
"Field2"
]
}
}
}
但是,这也会让我回归,这样我仍然可以得到#22; John Doe"当我输入john x。
答案 0 :(得分:3)
正如我在上面的评论中所解释的那样,随着索引的增长,应该不惜一切代价避免使用前缀通配符,因为这将迫使ES执行完整的索引扫描。我仍然相信ngrams(更准确地说是edge-ngrams)是要走的路,所以我在下面捅了一下。
我们的想法是索引输入的所有后缀,然后使用prefix
query来匹配任何后缀,因为搜索前缀不会遇到与搜索后缀相同的性能问题。因此,我们的想法是将john doe
编入索引如下:
john doe
ohn doe
hn doe
n doe
doe
oe
e
这样,使用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"
}
}
}
}
}
然后我们可以索引一个示例文档:
PUT my_index/doc/1
{
"name": "john doe"
}
最后,以下所有搜索都将返回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"
}
}
}
答案 1 :(得分:2)
这对我有用。 而不是ngram,将您的数据索引为关键字。 并使用通配符正则表达式匹配来匹配单词。
"query": {
"bool": {
"should": [
{
"wildcard": { "Field1": "*" + term + "*" }
},
{
"wildcard": { "Field2": "*" + term + "*" }
}
],
"minimum_should_match": 1
}
}