我正在尝试为最终用户提供搜索类型,这更像sqlserver。我能够为给定的SQL场景实现ES查询:
select * from table where name like '%pete%' and type != 'xyz and type!='abc'
但是ES查询不适用于此sql查询
select * from table where name like '%peter tom%' and type != 'xyz and type!='abc'
在我的elasticsearch以及通配符查询中,我还需要执行一些布尔过滤查询
{ "query": { "filtered": { "filter": { "bool": { "should": [ { "query": { "wildcard": { "name": { "value": "*pete*" } } } } ], "must_not": [ { "match": { "type": "xyz" } }, { "match": { "type": "abc" } } ] } } } } }
上面的带有通配符搜索的弹性查询可以很好地工作,并让我获得所有与pete匹配且不是xyz和abc类型的文档。但是当我尝试使用以空格分隔的2个独立单词执行通配符时,相同的查询返回我为空,如图所示下面。例如
{ "query": { "filtered": { "filter": { "bool": { "should": [ { "query": { "wildcard": { "name": { "value": "*peter tom*" } } } } ], "must_not": [ { "match": { "type": "xyz" } }, { "match": { "type": "abc" } } ] } } } } }
我的映射如下:
{ "properties": { "name": { "type": "string" } "type": { "type": "string" } } }
我应该使用什么查询才能对以空格分隔的单词进行通配符搜索
最有效的解决方案涉及利用ngram标记器来标记name字段的某些部分。例如,如果您有一个名称,如petertomson,则ngram令牌生成器将对它进行令牌化和索引,如下所示:
name
petertomson
因此,将其编入索引后,搜索这些标记中的任何一个都会peter thomson在其中检索您的文档。
peter thomson
让我们创建索引:
PUT likequery { "settings": { "analysis": { "analyzer": { "my_ngram_analyzer": { "tokenizer": "my_ngram_tokenizer" } }, "tokenizer": { "my_ngram_tokenizer": { "type": "nGram", "min_gram": "2", "max_gram": "15" } } } }, "mappings": { "typename": { "properties": { "name": { "type": "string", "fields": { "search": { "type": "string", "analyzer": "my_ngram_analyzer" } } }, "type": { "type": "string", "index": "not_analyzed" } } } } }
然后,您将可以通过一个简单且非常有效的term查询进行如下搜索:
term
POST likequery/_search { "query": { "bool": { "should": [ { "term": { "name.search": "peter tom" } } ], "must_not": [ { "match": { "type": "xyz" } }, { "match": { "type": "abc" } } ] } } }