UPDATE :

在阅读Richa的解释和推荐的blog post之后,该问题似乎已得到解决,但是在确认之前我需要进行更多测试。

首先,应按照Richa的建议更改同义词格式:

[“绿色=>卡其色,绿色”,“宠物=>猫,宠物”]

然后,我必须在索引映射中指定search_analyzerindex_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将替换为khakigreen。使用analyze api可以看到
GET stack-57703209/_analyze
{
  "text": "khaki",
  "analyzer": "lowercaseWhiteSpaceAnalyzer"
}

这将返回两个 token khakigreen
{
  "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所看到的那样,单词khakikhakigreen 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博客详细解释了这一点。
希望这可以帮助!!

09-11 18:39