Elastic Search数组字段匹配异常:仅返回单条结果求助
问题解决:Elasticsearch搜索数组字段仅返回部分匹配结果
问题描述
使用PHP代码在Elasticsearch中搜索categories数组字段包含32的记录,当前仅返回文档1(categories: [32]),但期望同时返回文档2(categories: [32,50])。
当前PHP代码:
$categories= 32; $params = [ 'index' => 'indexname', 'body' => [ 'query' => [ 'term' => [ 'categories' => $categories, ], ], 'size' => 100 ] ]; $response = $client->search($params);
categories字段映射:
"categories": { "type": "text", "analyzer": "global_search_analyzer", "fielddata": true }
原因分析
categories被设置为text类型并使用自定义分词器,数组中的数值会被分词器拆分处理(比如可能将32拆分为"3"和"2")。而term查询是精确匹配分词后的词项,文档2中的32经过分词后无法和查询的"32"精确匹配,因此不会被命中。
解决方案
方案1:修改字段映射(最优)
由于categories存储的是ID数组,适合使用keyword类型(不分词,保留原始值)。可以添加keyword子字段(不影响原有text字段的使用):
更新后的字段映射:
"categories": { "type": "text", "analyzer": "global_search_analyzer", "fielddata": true, "fields": { "keyword": { "type": "keyword" } } }
更新映射后需重新索引所有文档,然后修改PHP查询代码,使用categories.keyword字段进行精确匹配:
$categories= 32; $params = [ 'index' => 'indexname', 'body' => [ 'query' => [ 'term' => [ 'categories.keyword' => $categories, ], ], 'size' => 100 ] ]; $response = $client->search($params);
方案2:使用match查询(临时替代)
如果暂时无法修改映射和重新索引,可以使用match查询,它会使用相同的分词器处理查询词,匹配分词后的结果:
$categories= 32; $params = [ 'index' => 'indexname', 'body' => [ 'query' => [ 'match' => [ 'categories' => $categories, ], ], 'size' => 100 ] ]; $response = $client->search($params);
注意:该方案依赖分词器规则,若分词器配置变更可能导致匹配失效,仅作为临时解决方案,优先推荐方案1。
内容的提问来源于stack exchange,提问作者Sukhpal Singh
相关产品推荐
相关产品推荐

