我有一个带有产品的弹性搜索5.3服务器。 每个产品都有一个14位数的产品代码,必须按照以下规则进行搜索。完整代码应与仅包含最后9位数字,最后6位数字,最后5位数字或最后4位数字的搜索词匹配。
为了实现这一目标,我创建了一个自定义分析器,它使用模式捕获令牌过滤器在索引时创建适当的标记。这似乎工作正常。 _analyse API显示正确的术语已创建。
要从弹性搜索中获取文档,我正在使用multi_match cross_fields bool查询同时搜索多个字段。
当我的查询字符串具有与产品代码匹配的部分以及与任何其他字段匹配的部分时,不会返回任何结果,但是当我单独搜索每个部分时,将返回相应的结果。此外,当我有多个部分跨越除产品代码之外的任何字段时,将返回正确的结果。
我的maping和分析器:
PUT /store
{
"mappings": {
"products":{
"properties":{
"productCode":{
"analyzer": "ProductCode",
"search_analyzer": "standard",
"type": "text"
},
"description": {
"type": "text"
},
"remarks": {
"type": "text"
}
}
}
},
"settings": {
"analysis": {
"filter": {
"ProductCodeNGram": {
"type": "pattern_capture",
"preserve_original": "true",
"patterns": [
"\\d{5}(\\d{9})",
"\\d{8}(\\d{6})",
"\\d{9}(\\d{5})",
"\\d{10}(\\d{4})"
]
}
},
"analyzer": {
"ProductCode": {
"filter": ["ProductCodeNGram"],
"type": "custom",
"preserve_original": "true",
"tokenizer": "standard"
}
}
}
}
}
查询
GET /store/products/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "[query_string]",
"fields": ["productCode", "description", "remarks"],
"type": "cross_fields",
"operator": "and"
}
}
]
}
}
}
示例数据
POST /store/products
{
"productCode": "999999123456789",
"description": "Foo bar",
"remarks": "Foobar"
}
以下查询字符串都返回一个结果:
“456789”,“foo”,“foobar”,“foo foobar”。
但是query_string“foo 456789”没有返回任何结果。
我很好奇为什么最后一次搜索没有返回任何结果。我相信它应该。
答案 0 :(得分:2)
问题是你在使用不同分析器的字段上进行交叉字段。交叉字段仅适用于使用相同分析器的字段。事实上,它在执行交叉字段之前通过分析器对字段进行分组。您可以在本文档中找到更多信息。
答案 1 :(得分:0)
尽管cross_fields
在其操作的各个字段上需要使用相同的分析器,但我很幸运使用tie_breaker参数来权衡其他字段(使用不同的分析器)的总得分。
这样做还有一个好处,就是也可以在最终得分中计算每场助攻。
以下是使用您的查询的示例:
GET /store/products/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "[query_string]",
"fields": ["productCode", "description", "remarks"],
"type": "cross_fields",
"tie_breaker": 1 # You may need to tweak this
}
}
]
}
}
}
我还删除了operator
字段,因为我相信使用“ AND”运算符会导致对不具有相同分析器的字段进行不正确的评分。