ElasticSearch使用踩坑——term查询对中文字符串无效,无法查询正确数据结果(ElasticSearch中keyword设置的作用)

    技术2023-04-04  97

    一定要注意api版本和elasticsearch版本的搭配,虽然有上下版本兼容,但是兼容的很奇怪。到底加不加keyword,需要查看一下创建的索引结构,如果索引结构中字段下有一个keyword,那就需要添加keyword进行查询。

    使用term查询无法生效。

    @Field(type = FieldType.Keyword) QueryBuilder queryBuilder = QueryBuilders.termQuery("source", "淘宝");

    准确来说并不是无法生效,而是没有查询出数据。首先说一下对于term查询的语义: term query会去倒排索弓|中寻找确切的term,它并不知道分词器的存在。这种查询适合keyword、numeric. date. term表示查询某个字段里含有某个关键词的文档,terms表示查询某个字段里合有多个关键词的文档

    注意:查询某个字段里含有某个关键词的文档,这句话就说明了直接对字段进行term查询实际上还是模糊搜索,区别只不过是不会对搜索的输入字符串进行分词处理而已。如果想通过term查询到数据,那么term查询的字段在索引库中就必须有与term查询条件相同的索引词,否则就是无法查询到结果的。

    最后发现原因还是在于keyword这个属性的语义。

    keyword属性,网上很多文章说在字段上设置该属性表示对于该字段不进行分词索引,但实际上该字段仍然会被分词,所以如果分词之后的索引库中不包含该字段的完整词,那么直接对该字段用上面的term查询是完全无法查询的。

    可以尝试将检索条件”淘宝“改为”淘“或者”宝“就可以检索出结果,这说明还是进行了分词处理。

    那设置keyword有什么用?

    实际上,keyword属性的设置是添加了一个额外字段,这个字段就是source.keyword,也就是es在source字段之下额外生成添加了一个属性字段是keyword,这个keyword才是真正的不分词的索引字段,source.keyword字段才是真正意义上的不分词处理字段。而索引也是索引该字段才是真正的精确匹配。大概类似于下面的maping

    "mapping": { "properties": { "id": { "type": "long" }, "searchField": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } }

    所以,在对keyword属性字段进行精确查询时,应该改为如下代码

    QueryBuilder queryBuilder = QueryBuilders.termQuery("source.keyword", "淘宝");
    Processed: 0.009, SQL: 10