Elasticsearch搜索在带有特殊字符和通配符的字段中失败

8

我在Elasticsearch中有一个字段,其值为"PEI.H.02354.01."。当我使用querystring进行搜索时,

{  
   "query":{  
      "query_string":{  
         "query":"field:PEI.H.02354.01.",
         "default_operator":"AND"
      }
   }
}

如果我使用通配符搜索,则不会返回任何结果,但正确的行为应该是返回结果。

{  
   "query":{  
      "query_string":{  
         "query":"field:PEI.H.02354.01.*",
         "default_operator":"AND"
      }
   }
}

该字段是字符串类型并进行了分析。以下是创建索引的代码,包括分析器和映射。

{
   "settings":{  
      "analysis":{  
         "analyzer":{  
            "number":{  
               "type":"custom",
               "tokenizer":"keyword",
               "filter":[  
                  "lowercase"
               ],
               "char_filter":[  
                  "number_filter"
               ]
            },
            "diacritical":{  
               "type":"custom",
               "tokenizer":"standard",
               "filter":[  
                  "standard",
                  "lowercase",
                  "asciifolding",
                  "nfd_normalizer"
               ]
            }
         },
         "filter":{  
            "nfd_normalizer":{  
               "type":"icu_normalizer",
               "name":"nfc"
            }
         },
         "char_filter":{  
            "number_filter":{  
               "type":"pattern_replace",
               "pattern":"[^\\d]+",
               "replacement":""
            }
         }
      }
   },
   "mappings":{  
      "testType":{  
         "_source":{  
            "enabled":false
         },
         "_all":{  
            "enabled":false
         },
         "_timestamp":{  
            "enabled":"true",
            "store":"yes"
         },
         "properties":{  
            "field":{  
               "store":"yes",
               "type":"string",
               "index":"analyzed",
               "analyzer":"diacritical"
            }
         }
     }    
}

最后,一个插入示例是

{
    field: "PEI.H.02354.01."
}

有没有人知道为什么会出现这种情况以及如何解决?

1个回答

8
请查看query_string文档:
默认情况下,通配符不会被分析-它们会变成小写( lowercase_expanded_terms的默认值为true),但不会进行进一步的分析。
你存储的数据被分为两个术语。
curl -XGET 'localhost:9200/myindex/_analyze?analyzer=diacritical&pretty' -d 'PEI.H.02354.01'
{
  "tokens" : [ {
    "token" : "pei.h",
    "start_offset" : 0,
    "end_offset" : 5,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "02354.01",
    "start_offset" : 6,
    "end_offset" : 14,
    "type" : "<NUM>",
    "position" : 2
  } ]
}

但是,由于您使用通配符的搜索术语仅转换为pei.h.02354.01.*,因此不会匹配。

但是,如果将analyze_wildcard设置为true,则可以获得结果:

curl -XGET "http://localhost:9200/myindex/testType/_search?pretty" -d'
> {
>    "query":{
>       "query_string":{
>          "query":"field:PEI.H.02354.01.*",
>          "default_operator":"AND",
>          "analyze_wildcard": true
>       }
>    }
> }'
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.4142135,

使用这种方法确实会返回结果,但并非所有结果都是正确的,例如我还得到了PEI.H.4545.01。如果像你所说的那样,搜索词被分析,ES基本上搜索的是pei.h或02354.01,这是有道理的。但是否有一种方法可以避免这种情况,直接搜索PEI.H.02354.01,而不是将其拆分为两个词项? - dchar
听起来你想把PEI.H.02354.01作为一个字符串处理 - 如果是这样,你需要更改你的分析器,例如只在空格上进行标记化。 - Olly Cruickshank
可能对于这种搜索,您应该使用具有不同分析器的多字段。 - Olly Cruickshank
我使用空格分词器替换了标准分词器,这样的行为是正确的,即不会将标点符号作为分词处理。 - dchar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接