xref: /aosp_15_r20/external/icing/icing/index/iterator/doc-hit-info-iterator-or.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ICING_INDEX_ITERATOR_DOC_HIT_INFO_ITERATOR_OR_H_
16 #define ICING_INDEX_ITERATOR_DOC_HIT_INFO_ITERATOR_OR_H_
17 
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "icing/index/iterator/doc-hit-info-iterator.h"
24 
25 namespace icing {
26 namespace lib {
27 
28 // Given n iterators, will decide what the fastest Or-iterator implementation
29 // will be.
30 std::unique_ptr<DocHitInfoIterator> CreateOrIterator(
31     std::vector<std::unique_ptr<DocHitInfoIterator>> iterators);
32 
33 // Iterate over a logical OR of two child iterators.
34 class DocHitInfoIteratorOr : public DocHitInfoIterator {
35  public:
36   explicit DocHitInfoIteratorOr(std::unique_ptr<DocHitInfoIterator> left_it,
37                                 std::unique_ptr<DocHitInfoIterator> right_it);
38 
39   libtextclassifier3::StatusOr<TrimmedNode> TrimRightMostNode() && override;
40 
41   libtextclassifier3::Status Advance() override;
42 
GetCallStats()43   CallStats GetCallStats() const override {
44     return left_->GetCallStats() + right_->GetCallStats();
45   }
46 
47   std::string ToString() const override;
48 
MapChildren(const ChildrenMapper & mapper)49   void MapChildren(const ChildrenMapper &mapper) override {
50     left_ = mapper(std::move(left_));
51     right_ = mapper(std::move(right_));
52   }
53 
54   void PopulateMatchedTermsStats(
55       std::vector<TermMatchInfo> *matched_terms_stats,
56       SectionIdMask filtering_section_mask = kSectionIdMaskAll) const override {
57     if (doc_hit_info_.document_id() == kInvalidDocumentId) {
58       // Current hit isn't valid, return.
59       return;
60     }
61     current_->PopulateMatchedTermsStats(matched_terms_stats,
62                                         filtering_section_mask);
63     // If equal, then current_ == left_. Combine with results from right_.
64     if (left_document_id_ == right_document_id_) {
65       right_->PopulateMatchedTermsStats(matched_terms_stats,
66                                         filtering_section_mask);
67     }
68   }
69 
70  private:
71   std::unique_ptr<DocHitInfoIterator> left_;
72   std::unique_ptr<DocHitInfoIterator> right_;
73   // Pointer to the chosen iterator that points to the current doc_hit_info_. If
74   // both left_ and right_ point to the same docid, then chosen_ == left.
75   // chosen_ does not own the iterator it points to.
76   DocHitInfoIterator *current_;
77   DocumentId left_document_id_ = kMaxDocumentId;
78   DocumentId right_document_id_ = kMaxDocumentId;
79 };
80 
81 // Iterate over a logical OR of multiple child iterators.
82 //
83 // NOTE: DocHitInfoIteratorOr is a faster alternative to OR exactly 2 iterators.
84 class DocHitInfoIteratorOrNary : public DocHitInfoIterator {
85  public:
86   explicit DocHitInfoIteratorOrNary(
87       std::vector<std::unique_ptr<DocHitInfoIterator>> iterators);
88 
89   libtextclassifier3::StatusOr<TrimmedNode> TrimRightMostNode() && override;
90 
91   libtextclassifier3::Status Advance() override;
92 
93   CallStats GetCallStats() const override;
94 
95   std::string ToString() const override;
96 
MapChildren(const ChildrenMapper & mapper)97   void MapChildren(const ChildrenMapper &mapper) override {
98     for (int i = 0; i < iterators_.size(); ++i) {
99       iterators_[i] = mapper(std::move(iterators_[i]));
100     }
101   }
102 
103   void PopulateMatchedTermsStats(
104       std::vector<TermMatchInfo> *matched_terms_stats,
105       SectionIdMask filtering_section_mask = kSectionIdMaskAll) const override {
106     if (doc_hit_info_.document_id() == kInvalidDocumentId) {
107       // Current hit isn't valid, return.
108       return;
109     }
110     for (size_t i = 0; i < current_iterators_.size(); i++) {
111       current_iterators_.at(i)->PopulateMatchedTermsStats(
112           matched_terms_stats, filtering_section_mask);
113     }
114   }
115 
116  private:
117   std::vector<std::unique_ptr<DocHitInfoIterator>> iterators_;
118   // Pointers to the iterators that point to the current doc_hit_info_.
119   // current_iterators_ does not own the iterators it points to.
120   std::vector<DocHitInfoIterator *> current_iterators_;
121 };
122 
123 }  // namespace lib
124 }  // namespace icing
125 
126 #endif  // ICING_INDEX_ITERATOR_DOC_HIT_INFO_ITERATOR_OR_H_
127