我想在ElasticSearch中编写查询,提供结果,其中包含搜索查询中的所有单词,但不仅作为完整的单词,而且作为子词。例如,如果我有具有以下值的文档:
{
"first_name":"didier",
"last_name":"drogba"
}并且我搜索“滴滴滴滴”,这个文档应该会被返回。如果我搜索"david drogba",那么document应该被忽略,因为它没有包含单词"david“,甚至连子单词都没有。我尝试使用ngram标记器,但无法达到我想要的效果。
我创建的索引
PUT doctors
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram"
}
}
}
}
}然后添加了映射
put doctors/_doc/_mapping
{
"properties": {
"first_name": {
"type": "text",
"analyzer": "my_analyzer"
},
"last_name": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}添加一些文档
post doctors/_doc/1
{
"first_name": "dito",
"last_name": "janelidze",
"specialism": "oftalmologist",
"location_name":"evex saburtalo clinic",
"brand": "Evex",
"address":"kavtaradze street N21"
}我的搜索查询看起来像这样
get doctors/_doc/_search
{
"query": {
"multi_match": {
"query": "david jane",
"fields": ["first_name", "last_name"]
}
}
}它为我提供了我插入的文档,但我不需要它,因为它不包含单词"david“
发布于 2018-11-30 20:05:56
+1对于运算符“和”对于每个words.Use this,对我都有效(也可以用于自动补全)。
settings:
analysis": {
"filter": {
"name_ngrams": {
"max_gram": "20",
"type": "edgeNGram",
"min_gram": "1",
"side": "front"
}
},
"analyzer": {
"partial_name": {
"type": "custom",
"filter": [
"lowercase",
"name_ngrams",
"standard",
"asciifolding"
],
"tokenizer": "standard"
},
"full_name": {
"type": "custom",
"filter": [
"standard",
"lowercase",
"asciifolding"
],
"tokenizer": "standard"
}
}
mapping:
"first_name": {
"type": "text",
"index_analyzer": "partial_name",
"search_analyzer": "full_name"
},
"last_name": {
"type": "text",
"index_analyzer": "partial_name",
"search_analyzer": "full_name"
},发布于 2018-11-30 20:14:46
要点1:映射更改
-Gram tokenizer将从输入单词中构造指定长度的单词。此长度被指定为映射中的min_gram和max_gram,如果不指定,则分别缺省为1和2。
我已经更新了您分别使用min_gram:3和max_gram:5提供的映射。
然后,N-Gram Tokenizer将创建令牌,例如对于didier,它们将是did, idi, die, ier, didi, idie, dier, didie, idier,最终被存储在倒排索引中。
分别使用默认值1和2作为min_gram和max_gram,请注意,didier和david会将id作为公共子字,这就是返回它们的原因。
映射
PUT doctors
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 3,
"max_gram": 6,
}
}
}
}
}要点2:查询更改
也就是说,尽管进行了映射更改,但如果您的查询字符串包含使用您所拥有的内容的david jane,它将在first_name OR last_name中搜索david or jane。这意味着仍然会返回文档dito janelidze (但得分低于具有david jane的文档)
使用运算符AND将在first_name或last_name中作为david AND jane进行搜索,这不是您要查找的内容。
相反,您可以使用下面的布尔查询或创建另一个名为name的字段,使用copy_to字段将first_name和last_name的值复制到该字段中,并使用该字段进行搜索。
查询
POST <your_index_name>/_search
{
"query": {
"bool":{
"must": [
{
"match": {
"first_name": "david"
}
},
{
"match": {
"last_name": "jane"
}
}
]
}
}
}不幸的是,您需要删除、重新创建索引并再次摄取文档,因为所需的更改是在映射级进行的。
希望这能有所帮助!
https://stackoverflow.com/questions/53555900
复制相似问题