UPDATE :
在阅读Richa的解释和推荐的blog post之后,该问题似乎已得到解决,但是在确认之前我需要进行更多测试。
首先,应按照Richa的建议更改同义词格式:
[“绿色=>卡其色,绿色”,“宠物=>猫,宠物”]
然后,我必须在索引映射中指定search_analyzer
和index_analyzer
:
"mappings": {
"properties": {
"phone_case": {
"type": "text",
"norms": false,
"index_analyzer": "standard",
"search_analyzer": "lowercaseWhiteSpaceAnalyzer"
}
}
}
在映射中添加了这两个属性后,我不需要在查询中使用
analyzer
。这些更改似乎使体裁扩展按预期在“term”和“match_phrase”查询中起作用。
Elasticsearch 7.2
同义词数据:
[ "khaki => khaki,green", "cat => cat,pet"]
索引映射:
{
settings: {
"analysis": {
"char_filter": {
"same_word": {
"type": "mapping",
"mappings": ["-=>", "&=>and"]
},
},
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": STOPWORD_FILE
},
"my_synonym": {
"type": "synonym",
"synonyms": [ "khaki => khaki,green", "cat => cat,pet"],
"tokenizer": "whitespace"
},
},
"analyzer": {
"lowercaseWhiteSpaceAnalyzer": {
"type": "custom",
"char_filter": ["html_strip", "same_word"],
"tokenizer": "standard",
"filter": [
"lowercase",
"my_stopwords",
"my_synonym",
]
},
}
}
}
}
物料 Realm :
"phone_case":{"type":"text","norms":false,"analyzer":"lowercaseWhiteSpaceAnalyzer"}
示例文件:
[
{
id: "1",
phone_case: "khaki,brushed and polished",
},
{
id: "2",
phone_case: "green,brushed",
},
{
id: "3",
phone_case: "black,matte"
}
]
“phone_case”字段是文本字段。
当我搜索卡其色时,我想查找仅包含卡其色结果的文档,但不包括任何包含绿色的结果。另一方面,当搜索绿色时,我想获取带有绿色或卡其色的文档。那应该是流派扩展应该做的。
术语级别查询可以很好地用于以下目的:
{
"sort": [
{
"updated": {
"order": "desc"
}
}
],
"size": 10,
"from": 0,
"query": {
"bool": {
"filter": {
"term": {
"phone_case": "khaki"
}
}
}
}
它设法返回包含卡其色的文档。
但是,使用 match_phrase ,它将返回带有卡其色或绿色的文档。那不是我所期望的。我想获取包含卡其色而不是绿色的文档:
{
"sort": [
{
"updated": {
"order": "desc"
}
}
],
"size": 10,
"from": 0,
"query": {
"match_phrase": {
"phone_case": "khaki"
}
}
}
谁能告诉我匹配查询出了什么问题而无法排除包含“绿色”的结果?我想允许使用者以确切的顺序查找文本字段,但是匹配或 match_phrase 不适用于流派扩展同义词。
最佳答案
根据elastic documentation,当我们定义像a => b,c
这样的同义词时,解析为
# Explicit mappings match any token sequence on the LHS of "=>"
# and replace with all alternatives on the RHS. These types of mappings
# ignore the expand parameter in the schema.
因此,对于您的情况
"khaki => khaki,green"
,单词khaki
将替换为khaki
和green
。使用analyze
api可以看到GET stack-57703209/_analyze
{
"text": "khaki",
"analyzer": "lowercaseWhiteSpaceAnalyzer"
}
这将返回两个 token
khaki
和green
。{
"tokens" : [
{
"token" : "khaki",
"start_offset" : 0,
"end_offset" : 5,
"type" : "SYNONYM",
"position" : 0
},
{
"token" : "green",
"start_offset" : 0,
"end_offset" : 5,
"type" : "SYNONYM",
"position" : 0
}
]
}
如果您检查它的
green
GET stack-57703209/_analyze
{
"text": "green",
"analyzer": "lowercaseWhiteSpaceAnalyzer"
}
您将只获得一个 token
green
。{
"tokens" : [
{
"token" : "green",
"start_offset" : 0,
"end_offset" : 5,
"type" : "<ALPHANUM>",
"position" : 0
}
]
}
根据您的问题,您想要相反的意思,因此理想情况下,同义词应如下所示
"green => khaki,green"
not "khaki => khaki,green"
除此之外,您还在
index
时应用此分析器。因此,在为您的文档建立索引时,正如我们在上面使用analytics api所看到的那样,单词khaki
被khaki
和green
token 取代。当您运行
Term Query
时,它将搜索确切的术语{
"sort": [
{
"updated": {
"order": "desc"
}
}
],
"size": 10,
"from": 0,
"query": {
"bool": {
"filter": {
"term": {
"phone_case": "khaki"
}
}
}
}
如果您搜索
khaki
,您将仅获得第一个结果作为响应,因为术语查询不应用任何搜索分析器并匹配确切的术语,因此它将查找khaki
,而第二个文档phone_case: "green,brushed",
没有带khaki
的 token (可以使用分析来检查api),因此不会返回。但是,Match Query会应用默认情况下与
index analyzer
相同的分析器,在您的情况下为lowercaseWhiteSpaceAnalyzer
。因此,两个文件都被退回。因此,根据您的需求,您需要一个
search analyzer
而不是index analyzer
,因此您可以将索引设置更改为{
"settings": {
"analysis": {
"char_filter": {
"same_word": {
"type": "mapping",
"mappings": [
"-=>",
"&=>and"
]
}
},
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": "a, an"
},
"my_synonym": {
"type": "synonym",
"synonyms": [
"green => khaki,green", //NOTE THIS
"cat => cat,pet"
],
"tokenizer": "whitespace"
}
},
"analyzer": {
"lowercaseWhiteSpaceAnalyzer": {
"type": "custom",
"char_filter": [
"html_strip",
"same_word"
],
"tokenizer": "standard",
"filter": [
"lowercase",
"my_stopwords"
]
},
"synonym_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"my_synonym"
]
}
}
}
},
"mappings": {
"properties": {
"phone_case": {
"type": "text",
"norms": false,
"analyzer": "lowercaseWhiteSpaceAnalyzer"
}
}
}
}
然后改为指定
search analyzer
,例如{
"query": {
"match_phrase": {
"phone_case" : {
"query" : "green",
"analyzer" : "synonym_analyzer" // NOTE THIS
}
}
}
}
This博客详细解释了这一点。
希望这可以帮助!!