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

yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.0 by this push:
     new 551762d3a25 branch-4.0: [opt](inverted index) add BitmapQuery for 
boolean query composition #56408 (#56668)
551762d3a25 is described below

commit 551762d3a25d81d0a16c0c407c88d1f879a06514
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Sep 30 22:20:56 2025 +0800

    branch-4.0: [opt](inverted index) add BitmapQuery for boolean query 
composition #56408 (#56668)
    
    Cherry-picked from #56408
    
    Co-authored-by: zzzxl <[email protected]>
---
 .../query_v2/bitmap_query/bitmap_query.h           | 45 +++++++++++
 .../query_v2/bitmap_query/bitmap_scorer.h          | 83 ++++++++++++++++++++
 .../query_v2/bitmap_query/bitmap_weight.h          | 46 +++++++++++
 .../inverted_index/query_v2/boolean_query_test.cpp | 88 ++++++++++++++++++++++
 4 files changed, 262 insertions(+)

diff --git 
a/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_query.h
 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_query.h
new file mode 100644
index 00000000000..52503a2b979
--- /dev/null
+++ 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_query.h
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <memory>
+
+#include 
"olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_weight.h"
+#include "olap/rowset/segment_v2/inverted_index/query_v2/query.h"
+#include "roaring/roaring.hh"
+
+namespace doris::segment_v2::inverted_index::query_v2 {
+
+class BitmapQuery : public Query {
+public:
+    explicit BitmapQuery(std::shared_ptr<roaring::Roaring> bitmap) : 
_bitmap(std::move(bitmap)) {}
+    BitmapQuery(const roaring::Roaring& bitmap)
+            : _bitmap(std::make_shared<roaring::Roaring>(bitmap)) {}
+    ~BitmapQuery() override = default;
+
+    WeightPtr weight(bool /*enable_scoring*/) override {
+        return std::make_shared<BitmapWeight>(_bitmap);
+    }
+
+private:
+    std::shared_ptr<roaring::Roaring> _bitmap;
+};
+
+using BitmapQueryPtr = std::shared_ptr<BitmapQuery>;
+
+} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git 
a/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_scorer.h
 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_scorer.h
new file mode 100644
index 00000000000..7d510843799
--- /dev/null
+++ 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_scorer.h
@@ -0,0 +1,83 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <optional>
+
+#include "olap/rowset/segment_v2/inverted_index/query_v2/scorer.h"
+#include "roaring/roaring.hh"
+
+namespace doris::segment_v2::inverted_index::query_v2 {
+
+class BitmapScorer final : public Scorer {
+public:
+    explicit BitmapScorer(std::shared_ptr<roaring::Roaring> bitmap)
+            : _bitmap(std::move(bitmap)), _it(_bitmap->begin()) {
+        _doc = *_it;
+    }
+    ~BitmapScorer() override = default;
+
+    uint32_t advance() override {
+        if (_doc == TERMINATED) {
+            return TERMINATED;
+        }
+        ++_it;
+        if (!_it.i.has_value) {
+            _doc = TERMINATED;
+            return TERMINATED;
+        }
+        _doc = *_it;
+        return _doc;
+    }
+
+    uint32_t seek(uint32_t target) override {
+        if (_doc == TERMINATED) {
+            return TERMINATED;
+        }
+        if (target <= _doc) {
+            return _doc;
+        }
+        _it.equalorlarger(target);
+        if (!_it.i.has_value) {
+            _doc = TERMINATED;
+            return TERMINATED;
+        }
+        _doc = *_it;
+        return _doc;
+    }
+
+    uint32_t doc() const override { return _doc; }
+
+    uint32_t size_hint() const override {
+        uint64_t card = _bitmap->cardinality();
+        return static_cast<uint32_t>(
+                std::min<uint64_t>(card, 
std::numeric_limits<uint32_t>::max()));
+    }
+
+    float score() override { return 1.0F; }
+
+private:
+    std::shared_ptr<roaring::Roaring> _bitmap;
+    roaring::Roaring::const_iterator _it;
+    uint32_t _doc = TERMINATED;
+};
+
+} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git 
a/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_weight.h
 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_weight.h
new file mode 100644
index 00000000000..276ad072054
--- /dev/null
+++ 
b/be/src/olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_weight.h
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <memory>
+
+#include 
"olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_scorer.h"
+#include "olap/rowset/segment_v2/inverted_index/query_v2/weight.h"
+#include "roaring/roaring.hh"
+
+namespace doris::segment_v2::inverted_index::query_v2 {
+
+class BitmapWeight final : public Weight {
+public:
+    explicit BitmapWeight(std::shared_ptr<roaring::Roaring> bitmap) : 
_bitmap(std::move(bitmap)) {}
+    ~BitmapWeight() override = default;
+
+    ScorerPtr scorer(const CompositeReaderPtr& /*composite_reader*/) override {
+        if (_bitmap == nullptr || _bitmap->isEmpty()) {
+            return std::make_shared<EmptyScorer>();
+        }
+        return std::make_shared<BitmapScorer>(_bitmap);
+    }
+
+private:
+    std::shared_ptr<roaring::Roaring> _bitmap;
+};
+
+using BitmapWeightPtr = std::shared_ptr<BitmapWeight>;
+
+} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git 
a/be/test/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query_test.cpp 
b/be/test/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query_test.cpp
index 5144f5fc72f..3ce5bd11ce1 100644
--- 
a/be/test/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query_test.cpp
+++ 
b/be/test/olap/rowset/segment_v2/inverted_index/query_v2/boolean_query_test.cpp
@@ -26,6 +26,7 @@
 #include "common/status.h"
 #include "olap/rowset/segment_v2/index_query_context.h"
 #include "olap/rowset/segment_v2/inverted_index/analyzer/custom_analyzer.h"
+#include 
"olap/rowset/segment_v2/inverted_index/query_v2/bitmap_query/bitmap_query.h"
 #include "olap/rowset/segment_v2/inverted_index/query_v2/operator.h"
 #include 
"olap/rowset/segment_v2/inverted_index/query_v2/term_query/term_query.h"
 #include "olap/rowset/segment_v2/inverted_index/util/string_helper.h"
@@ -474,4 +475,91 @@ TEST_F(BooleanQueryTest, 
test_boolean_query_cross_fields_with_composite_reader)
     _CLDECDELETE(dir2);
 }
 
+TEST_F(BooleanQueryTest, test_boolean_query_bitmap_and_term) {
+    std::wstring field = StringHelper::to_wstring("name1");
+
+    auto context = std::make_shared<IndexQueryContext>();
+    context->collection_statistics = std::make_shared<CollectionStatistics>();
+    context->collection_similarity = std::make_shared<CollectionSimilarity>();
+
+    auto* dir = FSDirectory::getDirectory(kTestDir1.c_str());
+    auto* reader = IndexReader::open(dir, true);
+    ASSERT_TRUE(reader != nullptr);
+
+    auto composite_reader = std::make_unique<query_v2::CompositeReader>();
+    composite_reader->set_reader(field, reader);
+
+    roaring::Roaring bm;
+    for (uint32_t d = 0; d < static_cast<uint32_t>(reader->numDocs()); ++d) {
+        if (d % 8 == 0 || d % 8 == 1) {
+            bm.add(d);
+        }
+    }
+
+    query_v2::BooleanQuery::Builder builder(query_v2::OperatorType::OP_AND);
+    builder.add(std::make_shared<query_v2::TermQuery>(context, field,
+                                                      
StringHelper::to_wstring("apple")));
+    builder.add(std::make_shared<query_v2::BitmapQuery>(bm));
+    auto q = builder.build();
+
+    auto w = q->weight(false);
+    auto s = w->scorer(composite_reader);
+
+    uint32_t doc = s->doc();
+    uint32_t count = 0;
+    while (doc != query_v2::TERMINATED) {
+        EXPECT_TRUE(doc % 8 == 0 || doc % 8 == 1);
+        ++count;
+        doc = s->advance();
+    }
+    EXPECT_EQ(count, 20);
+
+    reader->close();
+    _CLLDELETE(reader);
+    _CLDECDELETE(dir);
+}
+
+TEST_F(BooleanQueryTest, test_boolean_query_bitmap_or_term) {
+    std::wstring field = StringHelper::to_wstring("name1");
+
+    auto context = std::make_shared<IndexQueryContext>();
+    context->collection_statistics = std::make_shared<CollectionStatistics>();
+    context->collection_similarity = std::make_shared<CollectionSimilarity>();
+
+    auto* dir = FSDirectory::getDirectory(kTestDir1.c_str());
+    auto* reader = IndexReader::open(dir, true);
+    ASSERT_TRUE(reader != nullptr);
+
+    auto composite_reader = std::make_unique<query_v2::CompositeReader>();
+    composite_reader->set_reader(field, reader);
+
+    roaring::Roaring bm;
+    for (uint32_t d = 0; d < static_cast<uint32_t>(reader->numDocs()); ++d) {
+        if (d % 8 == 2 || d % 8 == 3) {
+            bm.add(d);
+        }
+    }
+
+    query_v2::BooleanQuery::Builder builder(query_v2::OperatorType::OP_OR);
+    builder.add(std::make_shared<query_v2::TermQuery>(context, field,
+                                                      
StringHelper::to_wstring("apple")));
+    builder.add(std::make_shared<query_v2::BitmapQuery>(bm));
+    auto q = builder.build();
+
+    auto w = q->weight(false);
+    auto s = w->scorer(composite_reader);
+
+    uint32_t doc = s->doc();
+    uint32_t count = 0;
+    while (doc != query_v2::TERMINATED) {
+        ++count;
+        doc = s->advance();
+    }
+    EXPECT_EQ(count, 60);
+
+    reader->close();
+    _CLLDELETE(reader);
+    _CLDECDELETE(dir);
+}
+
 } // namespace doris::segment_v2


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

Reply via email to