Elasticsearch跨索引查询如何对存在的字段过滤、不存在则忽略过滤条件?
解决方案
核心逻辑是在Bool查询的SHOULD子句中设置两个可命中的条件,满足任意一个即可返回:
- 文档属于第一个索引且
isShowable值为true - 文档属于第二个索引(无过滤条件)
你可以选择两种实现方案:
写法1:按索引名称区分(更严谨,无边界问题)
直接通过索引字段_index做区分,完全避免字段存在性判断的边界异常(比如第一个索引存在isShowable为null的文档),原生ES查询逻辑参考:
{ "query": { "bool": { "should": [ { "bool": { "must": [ { "term": { "_index": "firstIndex" } }, { "term": { "isShowable": true } } ] } }, { "term": { "_index": "secondIndex" } } ], "minimum_should_match": 1 } } }
对应的PHP代码:
Item::search($formattedRequest, function (Client $client, Search $body) { // 条件1:属于第一个索引且isShowable为true $firstIndexCondition = new BoolQuery(); $firstIndexCondition->add(new TermQuery("_index", firstIndex), BoolQuery::MUST); $firstIndexCondition->add(new TermQuery("isShowable", true), BoolQuery::MUST); // 条件2:属于第二个索引 $secondIndexCondition = new TermQuery("_index", secondIndex); $bool = new BoolQuery(); $bool->add($firstIndexCondition, BoolQuery::SHOULD); $bool->add($secondIndexCondition, BoolQuery::SHOULD); $bool->setMinimumShouldMatch(1); $body->addQuery($bool); return $client->search( ['index' => firstIndex . "," . secondIndex, 'body' => $body->toArray()], ); })->get();
写法2:按字段存在性判断(代码更简洁)
适合第一个索引所有文档都存在isShowable字段且无null值的场景:
Item::search($formattedRequest, function (Client $client, Search $body) { // 条件1:isShowable为true $showableQuery = new TermQuery("isShowable", true); // 条件2:isShowable字段不存在 $fieldNotExistsQuery = new BoolQuery(); $fieldNotExistsQuery->add(new ExistsQuery("isShowable"), BoolQuery::MUST_NOT); $bool = new BoolQuery(); $bool->add($showableQuery, BoolQuery::SHOULD); $bool->add($fieldNotExistsQuery, BoolQuery::SHOULD); $bool->setMinimumShouldMatch(1); $body->addQuery($bool); return $client->search( ['index' => firstIndex . "," . secondIndex, 'body' => $body->toArray()], ); })->get();
注意:
minimum_should_match必须设置为1,确保必须满足任意一个should条件才会返回文档,避免查询逻辑受其他条件影响出现异常。
内容的提问来源于stack exchange,提问作者Toto NaBendo
相关产品推荐
相关产品推荐

