From 5281eb01bbe09a95da9295607ed9291b01113c9b Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Wed, 6 Mar 2024 17:24:08 +0800 Subject: [PATCH] fix: query mismatch with non-intersecting OR and nested AND condition (#5452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind bug /area core /milestone 2.14.x #### What this PR does / why we need it: 修复了索引查询使用含有 OR 条件嵌套 AND 条件时若匹配数据集间无交集导致的查询结果不正确的问题 如伪查询:`or(query, and(otherQuery1, otherQuery2))` 问题描述:当 `query` 匹配的结果与 `and(otherQuery1, otherQuery2)` 匹配的结果无交集时 and 会将自身不匹配的数据剔除导致 `query` 无法匹配到而出现缺少数据的问题 #### Does this PR introduce a user-facing change? ```release-note None ``` --- .../halo/app/extension/index/query/And.java | 2 -- .../app/extension/index/query/AndTest.java | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/run/halo/app/extension/index/query/And.java b/api/src/main/java/run/halo/app/extension/index/query/And.java index 4719b881e..8a80b319f 100644 --- a/api/src/main/java/run/halo/app/extension/index/query/And.java +++ b/api/src/main/java/run/halo/app/extension/index/query/And.java @@ -25,8 +25,6 @@ public class And extends LogicalQuery { NavigableSet resultSet = null; for (Query query : childQueries) { NavigableSet currentResult = query.matches(indexView); - // Trim unneeded rows to shrink the dataset for the next query - indexView.removeByIdNotIn(currentResult); if (resultSet == null) { resultSet = Sets.newTreeSet(currentResult); } else { diff --git a/api/src/test/java/run/halo/app/extension/index/query/AndTest.java b/api/src/test/java/run/halo/app/extension/index/query/AndTest.java index 5beef4ee0..d96fcf070 100644 --- a/api/src/test/java/run/halo/app/extension/index/query/AndTest.java +++ b/api/src/test/java/run/halo/app/extension/index/query/AndTest.java @@ -94,4 +94,23 @@ public class AndTest { var resultSet = query.matches(indexView); assertThat(resultSet).containsExactly("100"); } + + @Test + void orAndMatch() { + var indexView = IndexViewDataSet.createEmployeeIndexView(); + // test the case when the data matched by the query does not intersect with the data + // matched by the and query + // or(query, and(otherQuery1, otherQuery2)) + var query = or( + // matched with id 101 + and(equal("lastName", "Day"), equal("managerId", "102")), + // matched with id 100, 103 + and( + equal("hireDate", "17"), + greaterThan("salary", "1800") + ) + ); + var resultSet = query.matches(indexView); + assertThat(resultSet).containsExactly("100", "101", "103"); + } }