This is an automated email from the ASF dual-hosted git repository.

yangsiyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e901d759989 [fix](inverted index) Handle minimum_should_match when no 
should clauses exist (#60150)
e901d759989 is described below

commit e901d759989a961527061158bf85d3decef4ac07
Author: zzzxl <[email protected]>
AuthorDate: Tue Jan 27 11:03:12 2026 +0800

    [fix](inverted index) Handle minimum_should_match when no should clauses 
exist (#60150)
---
 .../boolean_query/occur_boolean_weight.cpp         |  8 +--
 .../query_v2/occur_boolean_query_test.cpp          | 80 ++++++++++++++++++++++
 2 files changed, 83 insertions(+), 5 deletions(-)

diff --git 
a/be/src/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query/occur_boolean_weight.cpp
 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query/occur_boolean_weight.cpp
index 844d578338c..20ce9f15172 100644
--- 
a/be/src/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query/occur_boolean_weight.cpp
+++ 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query/occur_boolean_weight.cpp
@@ -96,10 +96,6 @@ template <typename CombinerT>
 std::optional<CombinationMethod> 
OccurBooleanWeight<ScoreCombinerPtrT>::build_should_opt(
         std::vector<ScorerPtr>& must_scorers, std::vector<ScorerPtr> 
should_scorers,
         CombinerT combiner, size_t num_all_scorers) {
-    if (should_scorers.empty()) {
-        return Ignored {};
-    }
-
     size_t adjusted_minimum = _minimum_number_should_match > num_all_scorers
                                       ? _minimum_number_should_match - 
num_all_scorers
                                       : 0;
@@ -109,7 +105,9 @@ std::optional<CombinationMethod> 
OccurBooleanWeight<ScoreCombinerPtrT>::build_sh
         return std::nullopt;
     }
 
-    if (adjusted_minimum == 0) {
+    if (adjusted_minimum == 0 && num_of_should_scorers == 0) {
+        return Ignored {};
+    } else if (adjusted_minimum == 0) {
         return Optional {scorer_union(std::move(should_scorers), combiner)};
     } else if (adjusted_minimum == 1) {
         return Required {scorer_union(std::move(should_scorers), combiner)};
diff --git 
a/be/test/olap/rowset/segment_v2/inverted_index/query_v2/occur_boolean_query_test.cpp
 
b/be/test/olap/rowset/segment_v2/inverted_index/query_v2/occur_boolean_query_test.cpp
index bcffa0d7082..9ed08a1385c 100644
--- 
a/be/test/olap/rowset/segment_v2/inverted_index/query_v2/occur_boolean_query_test.cpp
+++ 
b/be/test/olap/rowset/segment_v2/inverted_index/query_v2/occur_boolean_query_test.cpp
@@ -704,4 +704,84 @@ TEST_F(OccurBooleanQueryTest, OnlyMustNotClausesEmpty) {
     EXPECT_EQ(scorer->doc(), TERMINATED);
 }
 
+TEST_F(OccurBooleanQueryTest, 
MinimumShouldMatchExceedsShouldClausesReturnsEmpty) {
+    {
+        auto must_docs1 = generate_range_docs(0, 100);
+        auto must_docs2 = generate_range_docs(50, 150);
+        std::vector<std::pair<Occur, QueryPtr>> clauses;
+        clauses.emplace_back(Occur::MUST, 
std::make_shared<MockQuery>(must_docs1));
+        clauses.emplace_back(Occur::MUST, 
std::make_shared<MockQuery>(must_docs2));
+
+        OccurBooleanQuery query(std::move(clauses), 2);
+        auto weight = query.weight(false);
+        auto scorer = weight->scorer(_ctx);
+
+        EXPECT_EQ(scorer->doc(), TERMINATED);
+    }
+
+    {
+        auto must_docs = generate_range_docs(0, 100);
+        auto should_docs = generate_range_docs(0, 100);
+        std::vector<std::pair<Occur, QueryPtr>> clauses;
+        clauses.emplace_back(Occur::MUST, 
std::make_shared<MockQuery>(must_docs));
+        clauses.emplace_back(Occur::SHOULD, 
std::make_shared<MockQuery>(should_docs));
+
+        OccurBooleanQuery query(std::move(clauses), 2);
+        auto weight = query.weight(false);
+        auto scorer = weight->scorer(_ctx);
+
+        EXPECT_EQ(scorer->doc(), TERMINATED);
+    }
+
+    {
+        auto should_docs1 = generate_range_docs(0, 100);
+        auto should_docs2 = generate_range_docs(50, 150);
+        auto expected = set_intersection(should_docs1, should_docs2);
+
+        std::vector<std::pair<Occur, QueryPtr>> clauses;
+        clauses.emplace_back(Occur::SHOULD, 
std::make_shared<MockQuery>(should_docs1));
+        clauses.emplace_back(Occur::SHOULD, 
std::make_shared<MockQuery>(should_docs2));
+
+        OccurBooleanQuery query(std::move(clauses), 2);
+        auto weight = query.weight(false);
+        auto scorer = weight->scorer(_ctx);
+        auto result = collect_docs(scorer);
+
+        EXPECT_EQ(result.size(), expected.size());
+        EXPECT_EQ(to_set(result), to_set(expected));
+    }
+
+    {
+        auto must_docs = generate_range_docs(0, 100);
+        auto must_not_docs = generate_range_docs(50, 150);
+
+        std::vector<std::pair<Occur, QueryPtr>> clauses;
+        clauses.emplace_back(Occur::MUST, 
std::make_shared<MockQuery>(must_docs));
+        clauses.emplace_back(Occur::MUST_NOT, 
std::make_shared<MockQuery>(must_not_docs));
+
+        OccurBooleanQuery query(std::move(clauses), 2);
+        auto weight = query.weight(false);
+        auto scorer = weight->scorer(_ctx);
+
+        EXPECT_EQ(scorer->doc(), TERMINATED);
+    }
+}
+
+TEST_F(OccurBooleanQueryTest, 
MinimumShouldMatchZeroWithNoShouldClausesReturnsIgnored) {
+    auto must_docs1 = generate_range_docs(0, 100);
+    auto must_docs2 = generate_range_docs(50, 150);
+    auto expected = set_intersection(must_docs1, must_docs2);
+
+    std::vector<std::pair<Occur, QueryPtr>> clauses;
+    clauses.emplace_back(Occur::MUST, std::make_shared<MockQuery>(must_docs1));
+    clauses.emplace_back(Occur::MUST, std::make_shared<MockQuery>(must_docs2));
+
+    OccurBooleanQuery query(std::move(clauses), 0);
+    auto weight = query.weight(false);
+    auto scorer = weight->scorer(_ctx);
+    auto result = collect_docs(scorer);
+
+    EXPECT_EQ(result, expected);
+}
+
 } // namespace doris::segment_v2::inverted_index::query_v2


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to