diff --git a/core/analysis/pipeline_token_stream.hpp b/core/analysis/pipeline_token_stream.hpp index df92f65fd..4d4aa4272 100644 --- a/core/analysis/pipeline_token_stream.hpp +++ b/core/analysis/pipeline_token_stream.hpp @@ -70,22 +70,15 @@ class pipeline_token_stream final : public TypedAnalyzer, template bool visit_members(Visitor&& visitor) const { for (const auto& sub : pipeline_) { - if (sub.get_stream().type() == - type()) { // pipe inside pipe - forward visiting -#if IRESEARCH_DEBUG - const auto& sub_pipe = - dynamic_cast(sub.get_stream()); -#else - const auto& sub_pipe = - static_cast(sub.get_stream()); -#endif + const auto& stream = sub.get_stream(); + if (stream.type() == type()) { + // pipe inside pipe - forward visiting + const auto& sub_pipe = DownCast(stream); if (!sub_pipe.visit_members(visitor)) { return false; } - } else { - if (!visitor(sub.get_stream())) { - return false; - } + } else if (!visitor(sub.get_stream())) { + return false; } } return true; diff --git a/core/search/all_docs_provider.cpp b/core/search/all_docs_provider.cpp index 536841ff7..3520e71e5 100644 --- a/core/search/all_docs_provider.cpp +++ b/core/search/all_docs_provider.cpp @@ -26,7 +26,7 @@ namespace irs { -filter::ptr AllDocsProvider::Default(score_t boost) { +FilterWithBoost::Ptr AllDocsProvider::Default(score_t boost) { auto filter = std::make_unique(); filter->boost(boost); return filter; diff --git a/core/search/all_docs_provider.hpp b/core/search/all_docs_provider.hpp index e7e20947d..a066b839e 100644 --- a/core/search/all_docs_provider.hpp +++ b/core/search/all_docs_provider.hpp @@ -28,11 +28,11 @@ namespace irs { class AllDocsProvider { public: - using ProviderFunc = std::function; + using ProviderFunc = std::function; - static filter::ptr Default(score_t boost); + static FilterWithBoost::Ptr Default(score_t boost); - filter::ptr MakeAllDocsFilter(score_t boost) const { + FilterWithBoost::Ptr MakeAllDocsFilter(score_t boost) const { return all_docs_(boost); } diff --git a/core/search/all_filter.cpp b/core/search/all_filter.cpp index 16c5287ca..1bbca29fc 100644 --- a/core/search/all_filter.cpp +++ b/core/search/all_filter.cpp @@ -30,21 +30,24 @@ namespace irs { class all_query : public filter::prepared { public: explicit all_query(bstring&& stats, score_t boost) - : filter::prepared(boost), stats_(std::move(stats)) {} + : stats_{std::move(stats)}, boost_{boost} {} doc_iterator::ptr execute(const ExecutionContext& ctx) const final { auto& rdr = ctx.segment; return memory::make_managed(rdr, stats_.c_str(), ctx.scorers, - rdr.docs_count(), boost()); + rdr.docs_count(), boost_); } void visit(const SubReader&, PreparedStateVisitor&, score_t) const final { // No terms to visit } + score_t boost() const noexcept final { return boost_; } + private: bstring stats_; + score_t boost_; }; filter::prepared::ptr all::prepare(const PrepareContext& ctx) const { diff --git a/core/search/all_filter.hpp b/core/search/all_filter.hpp index e39e15222..f5d8bc052 100644 --- a/core/search/all_filter.hpp +++ b/core/search/all_filter.hpp @@ -27,7 +27,7 @@ namespace irs { // Filter returning all documents -class all : public filter { +class all : public FilterWithBoost { public: filter::prepared::ptr prepare(const PrepareContext& ctx) const final; diff --git a/core/search/boolean_filter.cpp b/core/search/boolean_filter.cpp index 8e9bc0f87..fca1bde98 100644 --- a/core/search/boolean_filter.cpp +++ b/core/search/boolean_filter.cpp @@ -29,35 +29,29 @@ #include "prepared_state_visitor.hpp" #include "search/boolean_query.hpp" +namespace irs { namespace { -// first - pointer to the innermost not "not" node -// second - collapsed negation mark -std::pair optimize_not(const irs::Not& node) { +std::pair optimize_not(const Not& node) { bool neg = true; - const irs::filter* inner = node.filter(); - while (inner && inner->type() == irs::type::id()) { + const auto* inner = node.filter(); + while (inner != nullptr && inner->type() == type::id()) { neg = !neg; - inner = static_cast(inner)->filter(); + inner = DownCast(inner)->filter(); } - return std::make_pair(inner, neg); + return std::pair{inner, neg}; } } // namespace - -namespace irs { - bool boolean_filter::equals(const filter& rhs) const noexcept { if (!filter::equals(rhs)) { return false; } const auto& typed_rhs = DownCast(rhs); - return filters_.size() == typed_rhs.size() && - std::equal(begin(), end(), typed_rhs.begin(), - [](const filter::ptr& lhs, const filter::ptr& rhs) { - return *lhs == *rhs; - }); + return std::equal( + begin(), end(), typed_rhs.begin(), typed_rhs.end(), + [](const auto& lhs, const auto& rhs) { return *lhs == *rhs; }); } filter::prepared::ptr boolean_filter::prepare(const PrepareContext& ctx) const { @@ -81,8 +75,8 @@ filter::prepared::ptr boolean_filter::prepare(const PrepareContext& ctx) const { std::vector incl; std::vector excl; - irs::filter::ptr all_docs_zero_boost; - irs::filter::ptr all_docs_no_boost; + FilterWithBoost::Ptr all_docs_zero_boost; + FilterWithBoost::Ptr all_docs_no_boost; group_filters(all_docs_zero_boost, incl, excl); @@ -95,21 +89,21 @@ filter::prepared::ptr boolean_filter::prepare(const PrepareContext& ctx) const { return PrepareBoolean(incl, excl, ctx); } -void boolean_filter::group_filters(filter::ptr& all_docs_zero_boost, +void boolean_filter::group_filters(FilterWithBoost::Ptr& all_docs_zero_boost, std::vector& incl, std::vector& excl) const { incl.reserve(size() / 2); excl.reserve(incl.capacity()); - const irs::filter* empty_filter{nullptr}; + const filter* empty_filter = nullptr; const auto is_or = type() == irs::type::id(); - for (auto begin = this->begin(), end = this->end(); begin != end; ++begin) { - if (irs::type::id() == (*begin)->type()) { - empty_filter = begin->get(); + for (const auto& filter : *this) { + if (irs::type::id() == filter->type()) { + empty_filter = filter.get(); continue; } - if (irs::type::id() == (*begin)->type()) { - const auto res = optimize_not(DownCast(**begin)); + if (irs::type::id() == filter->type()) { + const auto res = optimize_not(DownCast(*filter)); if (!res.first) { continue; @@ -117,7 +111,7 @@ void boolean_filter::group_filters(filter::ptr& all_docs_zero_boost, if (res.second) { if (!all_docs_zero_boost) { - all_docs_zero_boost = MakeAllDocsFilter(0.f); + all_docs_zero_boost = MakeAllDocsFilter(0.F); } if (*all_docs_zero_boost == *res.first) { @@ -135,7 +129,7 @@ void boolean_filter::group_filters(filter::ptr& all_docs_zero_boost, incl.push_back(res.first); } } else { - incl.push_back(begin->get()); + incl.push_back(filter.get()); } } if (empty_filter != nullptr) { @@ -167,7 +161,7 @@ filter::prepared::ptr And::PrepareBoolean(std::vector& incl, for (auto filter : incl) { if (*filter == *cumulative_all) { all_count++; - all_boost += filter->boost(); + all_boost += DownCast(*filter).boost(); } } if (all_count != 0) { @@ -191,7 +185,7 @@ filter::prepared::ptr And::PrepareBoolean(std::vector& incl, // resulting boost will be: new_boost * OR_BOOST * LEFT_BOOST. If we // substitute new_boost back we will get ( boost * OR_BOOST * ALL_BOOST + // boost * OR_BOOST * LEFT_BOOST) - original non-optimized boost value - auto left_boost = (*incl.begin())->boost(); + auto left_boost = (*incl.begin())->BoostImpl(); if (boost() != 0 && left_boost != 0 && !sub_ctx.scorers.empty()) { sub_ctx.boost = (sub_ctx.boost * boost() * all_boost + sub_ctx.boost * boost() * left_boost) / @@ -257,7 +251,7 @@ filter::prepared::ptr Or::PrepareBoolean(std::vector& incl, for (auto filter : incl) { if (*filter == *cumulative_all) { all_count++; - all_boost += filter->boost(); + all_boost += DownCast(*filter).boost(); incl_all = filter; } } diff --git a/core/search/boolean_filter.hpp b/core/search/boolean_filter.hpp index 8f746cdcd..b3ac88f10 100644 --- a/core/search/boolean_filter.hpp +++ b/core/search/boolean_filter.hpp @@ -31,7 +31,7 @@ namespace irs { // Represents user-side boolean filter as the container for other filters -class boolean_filter : public filter, public AllDocsProvider { +class boolean_filter : public FilterWithBoost, public AllDocsProvider { public: auto begin() const { return filters_.begin(); } auto end() const { return filters_.end(); } @@ -59,17 +59,17 @@ class boolean_filter : public filter, public AllDocsProvider { bool empty() const { return filters_.empty(); } size_t size() const { return filters_.size(); } - filter::prepared::ptr prepare(const PrepareContext& ctx) const override; + prepared::ptr prepare(const PrepareContext& ctx) const override; protected: bool equals(const filter& rhs) const noexcept final; - virtual filter::prepared::ptr PrepareBoolean( - std::vector& incl, std::vector& excl, - const PrepareContext& ctx) const = 0; + virtual prepared::ptr PrepareBoolean(std::vector& incl, + std::vector& excl, + const PrepareContext& ctx) const = 0; private: - void group_filters(filter::ptr& all_docs_no_boost, + void group_filters(FilterWithBoost::Ptr& all_docs_zero_boost, std::vector& incl, std::vector& excl) const; @@ -85,9 +85,9 @@ class And final : public boolean_filter { } protected: - filter::prepared::ptr PrepareBoolean(std::vector& incl, - std::vector& excl, - const PrepareContext& ctx) const final; + prepared::ptr PrepareBoolean(std::vector& incl, + std::vector& excl, + const PrepareContext& ctx) const final; }; // Represents disjunction @@ -102,45 +102,41 @@ class Or final : public boolean_filter { return *this; } - filter::prepared::ptr prepare(const PrepareContext& ctx) const final; + prepared::ptr prepare(const PrepareContext& ctx) const final; type_info::type_id type() const noexcept final { return irs::type::id(); } protected: - filter::prepared::ptr PrepareBoolean(std::vector& incl, - std::vector& excl, - const PrepareContext& ctx) const final; + prepared::ptr PrepareBoolean(std::vector& incl, + std::vector& excl, + const PrepareContext& ctx) const final; private: size_t min_match_count_{1}; }; // Represents negation -class Not : public filter, public AllDocsProvider { +class Not : public FilterWithBoost, public AllDocsProvider { public: - const irs::filter* filter() const { return filter_.get(); } + const filter* filter() const { return filter_.get(); } template const T* filter() const { - using type = - typename std::enable_if_t, T>; - - return static_cast(filter_.get()); + static_assert(std::is_base_of_v); + return static_cast(filter_.get()); } template T& filter(Args&&... args) { - using type = - typename std::enable_if_t, T>; - - filter_ = std::make_unique(std::forward(args)...); - return static_cast(*filter_); + static_assert(std::is_base_of_v); + filter_ = std::make_unique(std::forward(args)...); + return static_cast(*filter_); } void clear() { filter_.reset(); } bool empty() const { return nullptr == filter_; } - filter::prepared::ptr prepare(const PrepareContext& ctx) const final; + prepared::ptr prepare(const PrepareContext& ctx) const final; type_info::type_id type() const noexcept final { return irs::type::id(); diff --git a/core/search/boolean_query.cpp b/core/search/boolean_query.cpp index f585c135a..339a1bb0d 100644 --- a/core/search/boolean_query.cpp +++ b/core/search/boolean_query.cpp @@ -142,7 +142,7 @@ doc_iterator::ptr BooleanQuery::execute(const ExecutionContext& ctx) const { // exclusion part does not affect scoring at all auto excl = make_disjunction( {.segment = ctx.segment, .scorers = Scorers::kUnordered, .ctx = ctx.ctx}, - irs::ScoreMergeType::kSum, excl_begin, end); + irs::ScoreMergeType::kNoop, excl_begin, end); // got empty iterator for excluded if (doc_limits::eof(excl->value())) { @@ -156,7 +156,7 @@ doc_iterator::ptr BooleanQuery::execute(const ExecutionContext& ctx) const { void BooleanQuery::visit(const irs::SubReader& segment, irs::PreparedStateVisitor& visitor, score_t boost) const { - boost *= this->boost(); + boost *= boost_; if (!visitor.Visit(*this, boost)) { return; @@ -167,10 +167,11 @@ void BooleanQuery::visit(const irs::SubReader& segment, (*it)->visit(segment, visitor, boost); } } + void BooleanQuery::prepare(const PrepareContext& ctx, ScoreMergeType merge_type, queries_t queries, size_t exclude_start) { // apply boost to the current node - this->boost(ctx.boost); + boost_ *= ctx.boost; // nothrow block queries_ = std::move(queries); excl_ = exclude_start; @@ -214,7 +215,7 @@ doc_iterator::ptr MinMatchQuery::execute(const ExecutionContext& ctx, const auto size = size_t(std::distance(begin, end)); // 1 <= min_match_count - size_t min_match_count = std::max(size_t(1), min_match_count_); + size_t min_match_count = std::max(size_t{1}, min_match_count_); // check the size before the execution if (0 == size || min_match_count > size) { diff --git a/core/search/boolean_query.hpp b/core/search/boolean_query.hpp index ac7740f48..9c282d3d5 100644 --- a/core/search/boolean_query.hpp +++ b/core/search/boolean_query.hpp @@ -40,6 +40,8 @@ class BooleanQuery : public filter::prepared { void visit(const irs::SubReader& segment, irs::PreparedStateVisitor& visitor, score_t boost) const final; + score_t boost() const noexcept final { return boost_; } + void prepare(const PrepareContext& ctx, ScoreMergeType merge_type, queries_t queries, size_t exclude_start); @@ -65,8 +67,9 @@ class BooleanQuery : public filter::prepared { // excl_..queries.end() - excluded queries queries_t queries_; // index of the first excluded query - size_t excl_{0}; - ScoreMergeType merge_type_{ScoreMergeType::kSum}; + size_t excl_ = 0; + ScoreMergeType merge_type_ = ScoreMergeType::kSum; + score_t boost_ = kNoBoost; }; // Represent a set of queries joint by "And" diff --git a/core/search/column_existence_filter.cpp b/core/search/column_existence_filter.cpp index 1a154ae0b..6586c91c3 100644 --- a/core/search/column_existence_filter.cpp +++ b/core/search/column_existence_filter.cpp @@ -28,10 +28,10 @@ namespace irs { namespace { -class column_existence_query : public irs::filter::prepared { +class column_existence_query : public filter::prepared { public: column_existence_query(std::string_view field, bstring&& stats, score_t boost) - : filter::prepared(boost), field_{field}, stats_(std::move(stats)) {} + : field_{field}, stats_{std::move(stats)}, boost_{boost} {} doc_iterator::ptr execute(const ExecutionContext& ctx) const override { const auto& segment = ctx.segment; @@ -48,6 +48,8 @@ class column_existence_query : public irs::filter::prepared { // No terms to visit } + score_t boost() const noexcept final { return boost_; } + protected: doc_iterator::ptr iterator(const SubReader& segment, const column_reader& column, @@ -62,7 +64,7 @@ class column_existence_query : public irs::filter::prepared { if (auto* score = irs::get_mutable(it.get()); score) { CompileScore(*score, ord.buckets(), segment, empty_term_reader(column.size()), stats_.c_str(), *it, - boost()); + boost_); } } @@ -71,6 +73,7 @@ class column_existence_query : public irs::filter::prepared { std::string field_; bstring stats_; + score_t boost_; }; class column_prefix_existence_query : public column_existence_query { diff --git a/core/search/filter.cpp b/core/search/filter.cpp index 5803458c2..a0eb7fe78 100644 --- a/core/search/filter.cpp +++ b/core/search/filter.cpp @@ -37,6 +37,8 @@ struct EmptyQuery : public filter::prepared { void visit(const SubReader&, PreparedStateVisitor&, score_t) const final { // No terms to visit } + + score_t boost() const noexcept final { return kNoBoost; } }; EmptyQuery kEmptyQuery; diff --git a/core/search/filter.hpp b/core/search/filter.hpp index 86bcb0f67..e1232bf57 100644 --- a/core/search/filter.hpp +++ b/core/search/filter.hpp @@ -68,20 +68,12 @@ class filter { static prepared::ptr empty(); - explicit prepared(score_t boost = kNoBoost) noexcept : boost_(boost) {} - virtual doc_iterator::ptr execute(const ExecutionContext& ctx) const = 0; virtual void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const = 0; - score_t boost() const noexcept { return boost_; } - - protected: - void boost(score_t boost) noexcept { boost_ *= boost; } - - private: - score_t boost_; + virtual score_t boost() const noexcept = 0; }; using ptr = std::unique_ptr; @@ -90,26 +82,36 @@ class filter { bool operator==(const filter& rhs) const noexcept { return equals(rhs); } - virtual filter::prepared::ptr prepare(const PrepareContext& ctx) const = 0; - - score_t boost() const noexcept { return boost_; } - - void boost(score_t boost) noexcept { boost_ = boost; } + virtual prepared::ptr prepare(const PrepareContext& ctx) const = 0; virtual type_info::type_id type() const noexcept = 0; + // kludge for optimization in And::prepare + virtual score_t BoostImpl() const noexcept { return kNoBoost; } + protected: virtual bool equals(const filter& rhs) const noexcept { return type() == rhs.type(); } +}; + +class FilterWithBoost : public filter { + public: + using Ptr = std::unique_ptr; + + score_t boost() const noexcept { return boost_; } + + void boost(score_t boost) noexcept { boost_ = boost; } private: - score_t boost_{kNoBoost}; + score_t BoostImpl() const noexcept final { return boost(); } + + score_t boost_ = kNoBoost; }; // Convenient base class filters with options template -class filter_with_options : public filter { +class filter_with_options : public FilterWithBoost { public: using options_type = Options; using filter_type = typename options_type::filter_type; @@ -152,7 +154,7 @@ class filter_base : public filter_with_options { }; // Filter which returns no documents -class empty final : public filter { +class empty final : public FilterWithBoost { public: filter::prepared::ptr prepare(const PrepareContext& ctx) const final; diff --git a/core/search/multiterm_query.cpp b/core/search/multiterm_query.cpp index 7afe4787b..89b39b51c 100644 --- a/core/search/multiterm_query.cpp +++ b/core/search/multiterm_query.cpp @@ -107,7 +107,7 @@ namespace irs { void MultiTermQuery::visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const { if (auto state = states_.find(segment); state) { - visitor.Visit(*this, *state, boost * this->boost()); + visitor.Visit(*this, *state, boost * boost_); } } @@ -151,7 +151,7 @@ doc_iterator::ptr MultiTermQuery::execute(const ExecutionContext& ctx) const { IRS_ASSERT(entry.stat_offset < stats.size()); auto* stat = stats[entry.stat_offset].c_str(); CompileScore(*score, ord.buckets(), segment, *state->reader, stat, *docs, - entry.boost * boost()); + entry.boost * boost_); } IRS_ASSERT(it != std::end(itrs)); diff --git a/core/search/multiterm_query.hpp b/core/search/multiterm_query.hpp index 91eb30df4..171395322 100644 --- a/core/search/multiterm_query.hpp +++ b/core/search/multiterm_query.hpp @@ -37,9 +37,9 @@ class MultiTermQuery : public filter::prepared { explicit MultiTermQuery(States&& states, Stats&& stats, score_t boost, ScoreMergeType merge_type, size_t min_match) - : prepared{boost}, - states_{std::move(states)}, + : states_{std::move(states)}, stats_{std::move(stats)}, + boost_{boost}, merge_type_{merge_type}, min_match_{min_match} {} @@ -48,9 +48,12 @@ class MultiTermQuery : public filter::prepared { void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const final; + score_t boost() const noexcept final { return boost_; } + private: States states_; Stats stats_; + score_t boost_; ScoreMergeType merge_type_; size_t min_match_; }; diff --git a/core/search/nested_filter.cpp b/core/search/nested_filter.cpp index 533375dfd..dae3196f2 100644 --- a/core/search/nested_filter.cpp +++ b/core/search/nested_filter.cpp @@ -601,7 +601,8 @@ class ByNestedQuery : public filter::prepared { void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const final { - boost *= this->boost(); + // TODO(MBkkt) maybe use none_boost for NoneMatcher? + // boost *= this->boost(); if (!visitor.Visit(*this, boost)) { return; @@ -611,6 +612,8 @@ class ByNestedQuery : public filter::prepared { child_->visit(segment, visitor, boost); } + score_t boost() const noexcept final { return kNoBoost; } + private: DocIteratorProvider parent_; prepared::ptr child_; diff --git a/core/search/ngram_similarity_query.cpp b/core/search/ngram_similarity_query.cpp index 4a16ea2ee..aa2bb6e85 100644 --- a/core/search/ngram_similarity_query.cpp +++ b/core/search/ngram_similarity_query.cpp @@ -582,14 +582,14 @@ doc_iterator::ptr NGramSimilarityQuery::execute( if (itrs.size() == min_match_count_) { return memory::make_managed, SerialPositionsChecker>>( - std::move(itrs), segment, *query_state->field, boost(), stats_.c_str(), + std::move(itrs), segment, *query_state->field, boost_, stats_.c_str(), query_state->terms.size(), min_match_count_, ord); } // TODO(MBkkt) min_match_count_ == 1: disjunction for approx, // optimization for low threshold case return memory::make_managed, SerialPositionsChecker>>( - std::move(itrs), segment, *query_state->field, boost(), stats_.c_str(), + std::move(itrs), segment, *query_state->field, boost_, stats_.c_str(), query_state->terms.size(), min_match_count_, ord); } diff --git a/core/search/ngram_similarity_query.hpp b/core/search/ngram_similarity_query.hpp index 69767a406..d662ee19a 100644 --- a/core/search/ngram_similarity_query.hpp +++ b/core/search/ngram_similarity_query.hpp @@ -41,26 +41,29 @@ class NGramSimilarityQuery : public filter::prepared { NGramSimilarityQuery(size_t min_match_count, NGramStates&& states, bstring&& stats, score_t boost = kNoBoost) - : prepared{boost}, - min_match_count_{min_match_count}, + : min_match_count_{min_match_count}, states_{std::move(states)}, - stats_{std::move(stats)} {} + stats_{std::move(stats)}, + boost_{boost} {} doc_iterator::ptr execute(const ExecutionContext& ctx) const final; void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const final { if (const auto* state = states_.find(segment); state) { - visitor.Visit(*this, *state, boost * this->boost()); + visitor.Visit(*this, *state, boost * boost_); } } + score_t boost() const noexcept final { return boost_; } + doc_iterator::ptr ExecuteWithOffsets(const SubReader& rdr) const; private: size_t min_match_count_; NGramStates states_; bstring stats_; + score_t boost_; }; } // namespace irs diff --git a/core/search/phrase_query.cpp b/core/search/phrase_query.cpp index 661f09451..3eb350055 100644 --- a/core/search/phrase_query.cpp +++ b/core/search/phrase_query.cpp @@ -107,7 +107,7 @@ doc_iterator::ptr FixedPhraseQuery::execute(const ExecutionContext& ctx) const { return memory::make_managed>( std::move(itrs), std::move(positions), rdr, *phrase_state->reader, - stats_.c_str(), ord, boost()); + stats_.c_str(), ord, boost_); } doc_iterator::ptr FixedPhraseQuery::ExecuteWithOffsets( @@ -284,13 +284,13 @@ doc_iterator::ptr VariadicPhraseQuery::execute( return memory::make_managed< VariadicPhraseIterator>( std::move(conj_itrs), std::move(positions), rdr, *phrase_state->reader, - stats_.c_str(), ord, boost()); + stats_.c_str(), ord, boost_); } return memory::make_managed< VariadicPhraseIterator>( std::move(conj_itrs), std::move(positions), rdr, *phrase_state->reader, - stats_.c_str(), ord, boost()); + stats_.c_str(), ord, boost_); } doc_iterator::ptr VariadicPhraseQuery::ExecuteWithOffsets( diff --git a/core/search/phrase_query.hpp b/core/search/phrase_query.hpp index 4d79c67b4..9c10baa10 100644 --- a/core/search/phrase_query.hpp +++ b/core/search/phrase_query.hpp @@ -49,15 +49,15 @@ class PhraseQuery : public filter::prepared { PhraseQuery(states_t&& states, positions_t&& positions, bstring&& stats, score_t boost) noexcept - : prepared{boost}, - states_{std::move(states)}, + : states_{std::move(states)}, positions_{std::move(positions)}, - stats_{std::move(stats)} {} + stats_{std::move(stats)}, + boost_{boost} {} void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const final { if (auto state = states_.find(segment); state) { - boost *= this->boost(); + boost *= boost_; if constexpr (std::is_same_v) { visitor.Visit(DownCast(*this), *state, boost); } else if constexpr (std::is_same_v) { @@ -66,9 +66,12 @@ class PhraseQuery : public filter::prepared { } } + score_t boost() const noexcept final { return boost_; } + states_t states_; positions_t positions_; bstring stats_; + score_t boost_; }; class FixedPhraseQuery : public PhraseQuery { diff --git a/core/search/proxy_filter.cpp b/core/search/proxy_filter.cpp index fc7cb8e72..4b5dff9b4 100644 --- a/core/search/proxy_filter.cpp +++ b/core/search/proxy_filter.cpp @@ -197,6 +197,7 @@ struct proxy_query_cache { class proxy_query : public filter::prepared { public: explicit proxy_query(proxy_filter::cache_ptr cache) : cache_{cache} { + IRS_ASSERT(cache_); IRS_ASSERT(cache_->real_filter_prepared_); } @@ -225,6 +226,8 @@ class proxy_query : public filter::prepared { // No terms to visit } + score_t boost() const noexcept final { return kNoBoost; } + private: proxy_filter::cache_ptr cache_; }; diff --git a/core/search/same_position_filter.cpp b/core/search/same_position_filter.cpp index b329dfd28..ba71dc9da 100644 --- a/core/search/same_position_filter.cpp +++ b/core/search/same_position_filter.cpp @@ -110,7 +110,7 @@ class same_position_query : public filter::prepared { explicit same_position_query(states_t&& states, stats_t&& stats, score_t boost) - : prepared(boost), states_(std::move(states)), stats_(std::move(stats)) {} + : states_{std::move(states)}, stats_{std::move(stats)}, boost_{boost} {} void visit(const SubReader&, PreparedStateVisitor&, score_t) const final { // FIXME(gnusi): implement @@ -162,7 +162,7 @@ class same_position_query : public filter::prepared { IRS_ASSERT(score); CompileScore(*score, ord.buckets(), segment, *term_state.reader, - term_stats->c_str(), *docs, boost()); + term_stats->c_str(), *docs, boost_); } // add iterator @@ -180,9 +180,12 @@ class same_position_query : public filter::prepared { }); } + score_t boost() const noexcept final { return boost_; } + private: states_t states_; stats_t stats_; + score_t boost_; }; } // namespace diff --git a/core/search/term_query.cpp b/core/search/term_query.cpp index dffd848c6..30f39b1de 100644 --- a/core/search/term_query.cpp +++ b/core/search/term_query.cpp @@ -30,9 +30,7 @@ namespace irs { TermQuery::TermQuery(States&& states, bstring&& stats, score_t boost) - : filter::prepared(boost), - states_{std::move(states)}, - stats_{std::move(stats)} {} + : states_{std::move(states)}, stats_{std::move(stats)}, boost_{boost} {} doc_iterator::ptr TermQuery::execute(const ExecutionContext& ctx) const { const auto& rdr = ctx.segment; @@ -55,7 +53,7 @@ doc_iterator::ptr TermQuery::execute(const ExecutionContext& ctx) const { *state->cookie, ord.features(), {[&](const attribute_provider& attrs) { return front.bucket->prepare_scorer( rdr, state->reader->meta().features, - stats_.c_str() + front.stats_offset, attrs, boost()); + stats_.c_str() + front.stats_offset, attrs, boost_); }}, ctx.wand); } @@ -69,7 +67,7 @@ doc_iterator::ptr TermQuery::execute(const ExecutionContext& ctx) const { auto* score = irs::get_mutable(docs.get()); IRS_ASSERT(score); CompileScore(*score, ord_buckets, rdr, *state->reader, stats_.c_str(), - *docs, boost()); + *docs, boost_); } return docs; @@ -77,8 +75,8 @@ doc_iterator::ptr TermQuery::execute(const ExecutionContext& ctx) const { void TermQuery::visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const { - if (auto state = states_.find(segment); state) { - visitor.Visit(*this, *state, boost * this->boost()); + if (const auto* state = states_.find(segment); state) { + visitor.Visit(*this, *state, boost * boost_); } } diff --git a/core/search/term_query.hpp b/core/search/term_query.hpp index a1ced9565..3988a678b 100644 --- a/core/search/term_query.hpp +++ b/core/search/term_query.hpp @@ -40,9 +40,12 @@ class TermQuery : public filter::prepared { void visit(const SubReader& segment, PreparedStateVisitor& visitor, score_t boost) const final; + score_t boost() const noexcept final { return boost_; } + private: States states_; bstring stats_; + score_t boost_; }; } // namespace irs diff --git a/tests/search/boolean_filter_tests.cpp b/tests/search/boolean_filter_tests.cpp index 857afea6a..3aa89b609 100644 --- a/tests/search/boolean_filter_tests.cpp +++ b/tests/search/boolean_filter_tests.cpp @@ -237,11 +237,11 @@ struct seek_doc { namespace detail { -struct boosted : public irs::filter { +struct boosted : public irs::FilterWithBoost { struct prepared : irs::filter::prepared { explicit prepared(const basic_doc_iterator::docids_t& docs, irs::score_t boost) - : irs::filter::prepared(boost), docs(docs) {} + : docs{docs}, boost_{boost} {} irs::doc_iterator::ptr execute( const irs::ExecutionContext& ctx) const final { @@ -255,8 +255,13 @@ struct boosted : public irs::filter { // No terms to visit } + irs::score_t boost() const noexcept final { return boost_; } + basic_doc_iterator::docids_t docs; irs::bstring stats; + + private: + irs::score_t boost_; }; irs::filter::prepared::ptr prepare( @@ -1161,7 +1166,7 @@ TEST(boolean_query_boost, or_filter) { namespace detail { -struct unestimated : public irs::filter { +struct unestimated : public irs::FilterWithBoost { struct doc_iterator : irs::doc_iterator { irs::doc_id_t value() const final { // prevent iterator to filter out @@ -1187,6 +1192,8 @@ struct unestimated : public irs::filter { irs::score_t) const final { // No terms to visit } + + irs::score_t boost() const noexcept final { return irs::kNoBoost; } }; filter::prepared::ptr prepare( @@ -1199,7 +1206,7 @@ struct unestimated : public irs::filter { } }; -struct estimated : public irs::filter { +struct estimated : public irs::FilterWithBoost { struct doc_iterator : irs::doc_iterator { doc_iterator(irs::cost::cost_t est, bool* evaluated) { cost.reset([est, evaluated]() noexcept { @@ -1241,6 +1248,8 @@ struct estimated : public irs::filter { // No terms to visit } + irs::score_t boost() const noexcept final { return irs::kNoBoost; } + bool* evaluated; irs::cost::cost_t est; }; diff --git a/tests/search/proxy_filter_test.cpp b/tests/search/proxy_filter_test.cpp index cbf224a73..fd7027dc9 100644 --- a/tests/search/proxy_filter_test.cpp +++ b/tests/search/proxy_filter_test.cpp @@ -95,7 +95,7 @@ class doclist_test_iterator : public doc_iterator, private util::noncopyable { class doclist_test_query : public filter::prepared { public: doclist_test_query(const std::vector& documents, score_t) - : documents_(documents){}; + : documents_(documents) {} doc_iterator::ptr execute(const ExecutionContext&) const final { ++executes_; @@ -106,6 +106,8 @@ class doclist_test_query : public filter::prepared { // No terms to visit } + irs::score_t boost() const noexcept final { return kNoBoost; } + static size_t get_execs() noexcept { return executes_; } static void reset_execs() noexcept { executes_ = 0; }