From a91ea35083d79d63e925e3d5fe8f4735b90a17ce Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Mon, 18 Mar 2024 14:15:16 +0100 Subject: Change parent class of search::streaming::SameElementQueryNode from search::streaming::AndQueryNode to search:streaming::MultiTerm. --- .../streaming/same_element_query_node_test.cpp | 45 ++++++++++++++----- .../searchlib/query/streaming/equiv_query_node.cpp | 4 +- .../searchlib/query/streaming/equiv_query_node.h | 2 +- .../src/vespa/searchlib/query/streaming/query.cpp | 1 - .../vespa/searchlib/query/streaming/querynode.cpp | 28 ++++++++++-- .../vespa/searchlib/query/streaming/querynode.h | 1 + .../vespa/searchlib/query/streaming/queryterm.cpp | 4 +- .../vespa/searchlib/query/streaming/queryterm.h | 2 +- .../query/streaming/same_element_query_node.cpp | 51 ++++++++++++++++++---- .../query/streaming/same_element_query_node.h | 11 ++--- .../src/vespa/searchvisitor/rankprocessor.cpp | 4 +- .../src/vespa/searchvisitor/rankprocessor.h | 4 +- .../src/vespa/vsm/searcher/fieldsearcher.cpp | 6 +-- .../src/vespa/vsm/vsm/fieldsearchspec.cpp | 6 +-- 14 files changed, 123 insertions(+), 46 deletions(-) diff --git a/searchlib/src/tests/query/streaming/same_element_query_node_test.cpp b/searchlib/src/tests/query/streaming/same_element_query_node_test.cpp index ece6dc551b2..db1e5a1ef5d 100644 --- a/searchlib/src/tests/query/streaming/same_element_query_node_test.cpp +++ b/searchlib/src/tests/query/streaming/same_element_query_node_test.cpp @@ -1,12 +1,20 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include +#include +#include +#include +#include #include #include #include #include #include +using search::fef::MatchData; +using search::fef::SimpleTermData; +using search::fef::TermFieldHandle; +using search::fef::test::IndexEnvironment; using search::query::QueryBuilder; using search::query::Node; using search::query::SimpleQueryNodeTypes; @@ -44,11 +52,11 @@ TEST(SameElementQueryNodeTest, a_unhandled_sameElement_stack) const QueryNode & root = q.getRoot(); auto sameElement = dynamic_cast(&root); EXPECT_TRUE(sameElement != nullptr); - EXPECT_EQ(2u, sameElement->size()); + EXPECT_EQ(2u, sameElement->get_terms().size()); EXPECT_EQ("xyz_abcdefghij_xyzxyzx", sameElement->getIndex()); - auto term0 = dynamic_cast((*sameElement)[0].get()); + auto term0 = sameElement->get_terms()[0].get(); EXPECT_TRUE(term0 != nullptr); - auto term1 = dynamic_cast((*sameElement)[1].get()); + auto term1 = sameElement->get_terms()[1].get(); EXPECT_TRUE(term1 != nullptr); } @@ -75,15 +83,17 @@ TEST(SameElementQueryNodeTest, test_same_element_evaluate) auto * sameElem = dynamic_cast(&q.getRoot()); EXPECT_TRUE(sameElem != nullptr); EXPECT_EQ("field", sameElem->getIndex()); - EXPECT_EQ(3u, sameElem->size()); - verifyQueryTermNode("field.f1", (*sameElem)[0].get()); - verifyQueryTermNode("field.f2", (*sameElem)[1].get()); - verifyQueryTermNode("field.f3", (*sameElem)[2].get()); - - QueryTermList terms; - q.getLeaves(terms); + EXPECT_EQ(3u, sameElem->get_terms().size()); + verifyQueryTermNode("field.f1", sameElem->get_terms()[0].get()); + verifyQueryTermNode("field.f2", sameElem->get_terms()[1].get()); + verifyQueryTermNode("field.f3", sameElem->get_terms()[2].get()); + + QueryTermList leaves; + q.getLeaves(leaves); + EXPECT_EQ(1u, leaves.size()); + auto& terms = sameElem->get_terms(); EXPECT_EQ(3u, terms.size()); - for (QueryTerm * qt : terms) { + for (auto& qt : terms) { qt->resizeFieldId(3); } @@ -130,6 +140,19 @@ TEST(SameElementQueryNodeTest, test_same_element_evaluate) EXPECT_EQ(160, hits[3].element_weight()); EXPECT_EQ(0u, hits[3].position()); EXPECT_TRUE(sameElem->evaluate()); + + SimpleTermData td; + constexpr TermFieldHandle handle0 = 27; + constexpr TermFieldHandle handle_max = handle0; + td.addField(0).setHandle(handle0); + auto md = MatchData::makeTestInstance(handle_max + 1, handle_max + 1); + auto tfmd0 = md->resolveTermField(handle0); + tfmd0->setNeedInterleavedFeatures(true); + IndexEnvironment ie; + sameElem->unpack_match_data(2, td, *md, ie); + EXPECT_EQ(2, tfmd0->getDocId()); + EXPECT_EQ(0, tfmd0->getNumOccs()); + EXPECT_EQ(0, tfmd0->end() - tfmd0->begin()); } GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp index 3fcf983901d..4367dc1cd69 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp @@ -81,8 +81,8 @@ EquivQueryNode::unpack_match_data(uint32_t docid, const fef::ITermData& td, fef: unpack_match_data_helper(docid, td, match_data, hit_list, *this, is_filter(), index_env); } -EquivQueryNode* -EquivQueryNode::as_equiv_query_node() noexcept +const MultiTerm* +EquivQueryNode::as_multi_index_multi_term() const noexcept { return this; } diff --git a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h index a0485954675..ac87e14150b 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h +++ b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h @@ -17,7 +17,7 @@ public: bool evaluate() const override; const HitList & evaluateHits(HitList & hl) const override; void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env) override; - EquivQueryNode* as_equiv_query_node() noexcept override; + const MultiTerm* as_multi_index_multi_term() const noexcept override; const EquivQueryNode* as_equiv_query_node() const noexcept override; std::vector> steal_terms(); }; diff --git a/searchlib/src/vespa/searchlib/query/streaming/query.cpp b/searchlib/src/vespa/searchlib/query/streaming/query.cpp index 94d9acd02cd..25fcb8c123e 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/query.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/query.cpp @@ -95,7 +95,6 @@ QueryConnector::create(ParseItem::ItemType type) case search::ParseItem::ITEM_OR: case search::ParseItem::ITEM_WEAK_AND: return std::make_unique(); case search::ParseItem::ITEM_NOT: return std::make_unique(); - case search::ParseItem::ITEM_SAME_ELEMENT: return std::make_unique(); case search::ParseItem::ITEM_NEAR: return std::make_unique(); case search::ParseItem::ITEM_ONEAR: return std::make_unique(); case search::ParseItem::ITEM_RANK: return std::make_unique(); diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index 611e8d67d76..37f3b07058b 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,6 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor case ParseItem::ITEM_OR: case ParseItem::ITEM_WEAK_AND: case ParseItem::ITEM_NOT: - case ParseItem::ITEM_SAME_ELEMENT: case ParseItem::ITEM_NEAR: case ParseItem::ITEM_ONEAR: case ParseItem::ITEM_RANK: @@ -61,9 +61,7 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor if (nqn) { nqn->distance(queryRep.getNearDistance()); } - if ((type == ParseItem::ITEM_WEAK_AND) || - (type == ParseItem::ITEM_SAME_ELEMENT)) - { + if (type == ParseItem::ITEM_WEAK_AND) { qn->setIndex(queryRep.getIndexName()); } for (size_t i=0; i < arity; i++) { @@ -197,6 +195,9 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor case ParseItem::ITEM_EQUIV: qn = build_equiv_term(factory, queryRep, allowRewrite); break; + case ParseItem::ITEM_SAME_ELEMENT: + qn = build_same_element_term(factory, queryRep, allowRewrite); + break; default: skip_unknown(queryRep); break; @@ -335,6 +336,25 @@ QueryNode::build_equiv_term(const QueryNodeResultFactory& factory, SimpleQuerySt return eqn; } +std::unique_ptr +QueryNode::build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite) +{ + auto sen = std::make_unique(factory.create(), queryRep.getIndexName(), queryRep.getArity()); + auto arity = queryRep.getArity(); + sen->setWeight(queryRep.GetWeight()); + sen->setUniqueId(queryRep.getUniqueId()); + for (size_t i = 0; i < arity; ++i) { + queryRep.next(); + auto qn = Build(sen.get(), factory, queryRep, allow_rewrite); + auto qtp = dynamic_cast(qn.get()); + assert(qtp != nullptr); + qn.release(); + std::unique_ptr qt(qtp); + sen->add_term(std::move(qt)); + } + return sen; +} + void QueryNode::skip_unknown(SimpleQueryStackDumpIterator& queryRep) { diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.h b/searchlib/src/vespa/searchlib/query/streaming/querynode.h index fff3bb15d10..c891cd44363 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.h +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.h @@ -35,6 +35,7 @@ class QueryNode static std::unique_ptr build_weighted_set_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep); static std::unique_ptr build_phrase_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep); static std::unique_ptr build_equiv_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite); + static std::unique_ptr build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite); static void skip_unknown(SimpleQueryStackDumpIterator& queryRep); public: using UP = std::unique_ptr; diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp index 728b9a2ab76..8a1fe2004d0 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp @@ -147,8 +147,8 @@ QueryTerm::as_fuzzy_term() noexcept return nullptr; } -EquivQueryNode* -QueryTerm::as_equiv_query_node() noexcept +const MultiTerm* +QueryTerm::as_multi_index_multi_term() const noexcept { return nullptr; } diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h index e6b063231d6..4a108d880e9 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h @@ -106,7 +106,7 @@ public: virtual MultiTerm* as_multi_term() noexcept; virtual RegexpTerm* as_regexp_term() noexcept; virtual FuzzyTerm* as_fuzzy_term() noexcept; - virtual EquivQueryNode* as_equiv_query_node() noexcept; + virtual const MultiTerm* as_multi_index_multi_term() const noexcept; virtual const EquivQueryNode* as_equiv_query_node() const noexcept; virtual void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env); protected: diff --git a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp index 49d5fb0f9fb..ae1ae8d5230 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp @@ -1,30 +1,36 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "same_element_query_node.h" +#include +#include #include namespace search::streaming { +SameElementQueryNode::SameElementQueryNode(std::unique_ptr result_base, const string& index, uint32_t num_terms) noexcept + : MultiTerm(std::move(result_base), index, num_terms) +{ +} + +SameElementQueryNode::~SameElementQueryNode() = default; + bool SameElementQueryNode::evaluate() const { HitList hl; return ! evaluateHits(hl).empty(); } -void -SameElementQueryNode::addChild(QueryNode::UP child) { - assert(dynamic_cast(child.get()) != nullptr); - AndQueryNode::addChild(std::move(child)); -} - const HitList & SameElementQueryNode::evaluateHits(HitList & hl) const { hl.clear(); - if ( !AndQueryNode::evaluate()) return hl; - + const auto & children = get_terms(); + for (auto& child : children) { + if ( ! child->evaluate() ) { + return hl; + } + } HitList tmpHL; - const auto & children = getChildren(); unsigned int numFields = children.size(); unsigned int currMatchCount = 0; std::vector indexVector(numFields, 0); @@ -62,4 +68,31 @@ SameElementQueryNode::evaluateHits(HitList & hl) const return hl; } +void +SameElementQueryNode::unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment&) +{ + HitList list; + const HitList & hit_list = evaluateHits(list); + if (!hit_list.empty()) { + auto num_fields = td.numFields(); + /* + * Currently reports hit for all fields for query node instead of + * just the fields where the related subfields had matches. + */ + for (size_t field_idx = 0; field_idx < num_fields; ++field_idx) { + auto& tfd = td.field(field_idx); + auto field_id = tfd.getFieldId(); + auto tmd = match_data.resolveTermField(tfd.getHandle()); + tmd->setFieldId(field_id); + tmd->reset(docid); + } + } +} + +const MultiTerm* +SameElementQueryNode::as_multi_index_multi_term() const noexcept +{ + return this; +} + } diff --git a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h index 8e675feb569..8955071ba4a 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h +++ b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h @@ -2,21 +2,22 @@ #pragma once -#include "query.h" +#include "multi_term.h" namespace search::streaming { /** N-ary Same element operator. All terms must be within the same element. */ -class SameElementQueryNode : public AndQueryNode +class SameElementQueryNode : public MultiTerm { public: - SameElementQueryNode() noexcept : AndQueryNode("SAME_ELEMENT") { } + SameElementQueryNode(std::unique_ptr result_base, const string& index, uint32_t num_terms) noexcept; + ~SameElementQueryNode() override; bool evaluate() const override; const HitList & evaluateHits(HitList & hl) const override; - bool isFlattenable(ParseItem::ItemType) const override { return false; } - void addChild(QueryNode::UP child) override; + void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env) override; + const MultiTerm* as_multi_index_multi_term() const noexcept override; }; } diff --git a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp index 2a95bf8251b..cfaaac8b197 100644 --- a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp @@ -56,7 +56,7 @@ getFeature(const RankProgram &rankProgram) { } void -RankProcessor::resolve_fields_from_children(QueryTermData& qtd, MultiTerm& mt) +RankProcessor::resolve_fields_from_children(QueryTermData& qtd, const MultiTerm& mt) { vespalib::hash_set field_ids; for (auto& subterm : mt.get_terms()) { @@ -83,7 +83,7 @@ RankProcessor::resolve_fields_from_children(QueryTermData& qtd, MultiTerm& mt) } void -RankProcessor::resolve_fields_from_term(QueryTermData& qtd, search::streaming::QueryTerm& term) +RankProcessor::resolve_fields_from_term(QueryTermData& qtd, const search::streaming::QueryTerm& term) { vespalib::string expandedIndexName = vsm::FieldSearchSpecMap::stripNonFields(term.index()); const RankManager::View *view = _rankManagerSnapshot->getView(expandedIndexName); diff --git a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.h b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.h index f384f7d7acf..9cb3e49fc32 100644 --- a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.h +++ b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.h @@ -45,8 +45,8 @@ private: HitCollector::UP _hitCollector; std::unique_ptr _match_features_program; - void resolve_fields_from_children(QueryTermData& qtd, search::streaming::MultiTerm& mt); - void resolve_fields_from_term(QueryTermData& qtd, search::streaming::QueryTerm& term); + void resolve_fields_from_children(QueryTermData& qtd, const search::streaming::MultiTerm& mt); + void resolve_fields_from_term(QueryTermData& qtd, const search::streaming::QueryTerm& term); void initQueryEnvironment(); void initHitCollector(size_t wantedHitCount, bool use_sort_blob); void setupRankProgram(search::fef::RankProgram &program); diff --git a/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp b/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp index 72807bc6c34..b03ae07c910 100644 --- a/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp +++ b/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp @@ -192,9 +192,9 @@ FieldSearcher::init() void FieldIdTSearcherMap::prepare_term(const DocumentTypeIndexFieldMapT& difm, QueryTerm* qt, FieldIdT fid, vespalib::hash_set& seen, QueryTermList& onlyInIndex) { - auto equiv = qt->as_equiv_query_node(); - if (equiv != nullptr) { - for (auto& subterm : equiv->get_terms()) { + auto mimt = qt->as_multi_index_multi_term(); + if (mimt != nullptr) { + for (auto& subterm : mimt->get_terms()) { prepare_term(difm, subterm.get(), fid, seen, onlyInIndex); } return; diff --git a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp index c596b46a774..35ce1a07cfb 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp +++ b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp @@ -223,9 +223,9 @@ FieldSearchSpecMap::buildFieldsInQuery(const Query & query) const query.getLeaves(qtl); for (const auto & term : qtl) { - auto equiv = term->as_equiv_query_node(); - if (equiv != nullptr) { - for (const auto& subterm : equiv->get_terms()) { + auto mimt = term->as_multi_index_multi_term(); + if (mimt != nullptr) { + for (const auto& subterm : mimt->get_terms()) { addFieldsFromIndex(subterm->index(), fieldsInQuery); } } else { -- cgit v1.2.3 From 4b5012817431e6cb91a2d19235ffa768cf6cf88f Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Mon, 18 Mar 2024 14:34:03 +0100 Subject: Rewrite is disabled for nodes below SameElementQueryNode. --- searchlib/src/vespa/searchlib/query/streaming/querynode.cpp | 10 ++++------ searchlib/src/vespa/searchlib/query/streaming/querynode.h | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index 37f3b07058b..94a479fd2d3 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -27,9 +27,7 @@ namespace search::streaming { namespace { bool disableRewrite(const QueryNode * qn) { - return dynamic_cast (qn) || - dynamic_cast (qn) || - dynamic_cast(qn); + return dynamic_cast (qn); } bool possibleFloat(const QueryTerm & qt, const QueryTerm::string & term) { @@ -196,7 +194,7 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor qn = build_equiv_term(factory, queryRep, allowRewrite); break; case ParseItem::ITEM_SAME_ELEMENT: - qn = build_same_element_term(factory, queryRep, allowRewrite); + qn = build_same_element_term(factory, queryRep); break; default: skip_unknown(queryRep); @@ -337,7 +335,7 @@ QueryNode::build_equiv_term(const QueryNodeResultFactory& factory, SimpleQuerySt } std::unique_ptr -QueryNode::build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite) +QueryNode::build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep) { auto sen = std::make_unique(factory.create(), queryRep.getIndexName(), queryRep.getArity()); auto arity = queryRep.getArity(); @@ -345,7 +343,7 @@ QueryNode::build_same_element_term(const QueryNodeResultFactory& factory, Simple sen->setUniqueId(queryRep.getUniqueId()); for (size_t i = 0; i < arity; ++i) { queryRep.next(); - auto qn = Build(sen.get(), factory, queryRep, allow_rewrite); + auto qn = Build(sen.get(), factory, queryRep, false); auto qtp = dynamic_cast(qn.get()); assert(qtp != nullptr); qn.release(); diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.h b/searchlib/src/vespa/searchlib/query/streaming/querynode.h index c891cd44363..20e701e5c50 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.h +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.h @@ -35,7 +35,7 @@ class QueryNode static std::unique_ptr build_weighted_set_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep); static std::unique_ptr build_phrase_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep); static std::unique_ptr build_equiv_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite); - static std::unique_ptr build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep, bool allow_rewrite); + static std::unique_ptr build_same_element_term(const QueryNodeResultFactory& factory, SimpleQueryStackDumpIterator& queryRep); static void skip_unknown(SimpleQueryStackDumpIterator& queryRep); public: using UP = std::unique_ptr; -- cgit v1.2.3 From b700eeb73d8de490cdafbc3d004ed091e71e3c9e Mon Sep 17 00:00:00 2001 From: Tor Egge Date: Mon, 18 Mar 2024 17:24:35 +0100 Subject: Use multi_index_terms() returning boolean to differentiate between multi term nodes that all searches the same index (e.g. Phrase) and multi term nodes that searches multiple indexes (e.g. Equiv, SameElement). --- .../searchlib/query/streaming/equiv_query_node.cpp | 6 +++--- .../vespa/searchlib/query/streaming/equiv_query_node.h | 2 +- .../src/vespa/searchlib/query/streaming/multi_term.cpp | 18 ++++++++++++++++++ .../src/vespa/searchlib/query/streaming/multi_term.h | 7 ++++++- .../src/vespa/searchlib/query/streaming/queryterm.cpp | 12 ++++++------ .../src/vespa/searchlib/query/streaming/queryterm.h | 2 +- .../query/streaming/same_element_query_node.cpp | 6 +++--- .../query/streaming/same_element_query_node.h | 2 +- .../src/vespa/vsm/searcher/fieldsearcher.cpp | 7 +++---- .../src/vespa/vsm/vsm/fieldsearchspec.cpp | 6 +++--- 10 files changed, 45 insertions(+), 23 deletions(-) diff --git a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp index 4367dc1cd69..8878c8c5cdc 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.cpp @@ -81,10 +81,10 @@ EquivQueryNode::unpack_match_data(uint32_t docid, const fef::ITermData& td, fef: unpack_match_data_helper(docid, td, match_data, hit_list, *this, is_filter(), index_env); } -const MultiTerm* -EquivQueryNode::as_multi_index_multi_term() const noexcept +bool +EquivQueryNode::multi_index_terms() const noexcept { - return this; + return true; } const EquivQueryNode* diff --git a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h index ac87e14150b..997a861ee44 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h +++ b/searchlib/src/vespa/searchlib/query/streaming/equiv_query_node.h @@ -17,7 +17,7 @@ public: bool evaluate() const override; const HitList & evaluateHits(HitList & hl) const override; void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env) override; - const MultiTerm* as_multi_index_multi_term() const noexcept override; + bool multi_index_terms() const noexcept override; const EquivQueryNode* as_equiv_query_node() const noexcept override; std::vector> steal_terms(); }; diff --git a/searchlib/src/vespa/searchlib/query/streaming/multi_term.cpp b/searchlib/src/vespa/searchlib/query/streaming/multi_term.cpp index f5a09892551..2a96a967215 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/multi_term.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/multi_term.cpp @@ -51,4 +51,22 @@ MultiTerm::evaluate() const return false; } +MultiTerm* +MultiTerm::as_multi_term() noexcept +{ + return this; +} + +const MultiTerm* +MultiTerm::as_multi_term() const noexcept +{ + return this; +} + +bool +MultiTerm::multi_index_terms() const noexcept +{ + return false; +} + } diff --git a/searchlib/src/vespa/searchlib/query/streaming/multi_term.h b/searchlib/src/vespa/searchlib/query/streaming/multi_term.h index 9bf5f8de6b2..a2ae3d30d52 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/multi_term.h +++ b/searchlib/src/vespa/searchlib/query/streaming/multi_term.h @@ -29,7 +29,12 @@ public: std::unique_ptr terms, Normalizing normalizing); ~MultiTerm() override; void add_term(std::unique_ptr term); - MultiTerm* as_multi_term() noexcept override { return this; } + MultiTerm* as_multi_term() noexcept override; + const MultiTerm* as_multi_term() const noexcept override; + /* + * Terms below search in different indexes when multi_index_terms() returns true. + */ + virtual bool multi_index_terms() const noexcept; void reset() override; bool evaluate() const override; const std::vector>& get_terms() const noexcept { return _terms; } diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp index 8a1fe2004d0..07fc60d2243 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp @@ -135,20 +135,20 @@ QueryTerm::as_multi_term() noexcept return nullptr; } -RegexpTerm* -QueryTerm::as_regexp_term() noexcept +const MultiTerm* +QueryTerm::as_multi_term() const noexcept { return nullptr; } -FuzzyTerm* -QueryTerm::as_fuzzy_term() noexcept +RegexpTerm* +QueryTerm::as_regexp_term() noexcept { return nullptr; } -const MultiTerm* -QueryTerm::as_multi_index_multi_term() const noexcept +FuzzyTerm* +QueryTerm::as_fuzzy_term() noexcept { return nullptr; } diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h index 4a108d880e9..78b0a1fea7d 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h @@ -104,9 +104,9 @@ public: void setFuzzyPrefixLength(uint32_t fuzzyPrefixLength) { _fuzzyPrefixLength = fuzzyPrefixLength; } virtual NearestNeighborQueryNode* as_nearest_neighbor_query_node() noexcept; virtual MultiTerm* as_multi_term() noexcept; + virtual const MultiTerm* as_multi_term() const noexcept; virtual RegexpTerm* as_regexp_term() noexcept; virtual FuzzyTerm* as_fuzzy_term() noexcept; - virtual const MultiTerm* as_multi_index_multi_term() const noexcept; virtual const EquivQueryNode* as_equiv_query_node() const noexcept; virtual void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env); protected: diff --git a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp index ae1ae8d5230..cd9c693ca1c 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.cpp @@ -89,10 +89,10 @@ SameElementQueryNode::unpack_match_data(uint32_t docid, const fef::ITermData& td } } -const MultiTerm* -SameElementQueryNode::as_multi_index_multi_term() const noexcept +bool +SameElementQueryNode::multi_index_terms() const noexcept { - return this; + return true; } } diff --git a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h index 8955071ba4a..37fb3dbba52 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h +++ b/searchlib/src/vespa/searchlib/query/streaming/same_element_query_node.h @@ -17,7 +17,7 @@ public: bool evaluate() const override; const HitList & evaluateHits(HitList & hl) const override; void unpack_match_data(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const fef::IIndexEnvironment& index_env) override; - const MultiTerm* as_multi_index_multi_term() const noexcept override; + bool multi_index_terms() const noexcept override; }; } diff --git a/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp b/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp index b03ae07c910..38e12a3054d 100644 --- a/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp +++ b/streamingvisitors/src/vespa/vsm/searcher/fieldsearcher.cpp @@ -192,9 +192,9 @@ FieldSearcher::init() void FieldIdTSearcherMap::prepare_term(const DocumentTypeIndexFieldMapT& difm, QueryTerm* qt, FieldIdT fid, vespalib::hash_set& seen, QueryTermList& onlyInIndex) { - auto mimt = qt->as_multi_index_multi_term(); - if (mimt != nullptr) { - for (auto& subterm : mimt->get_terms()) { + auto multi_term = qt->as_multi_term(); + if (multi_term != nullptr && multi_term->multi_index_terms()) { + for (auto& subterm : multi_term->get_terms()) { prepare_term(difm, subterm.get(), fid, seen, onlyInIndex); } return; @@ -206,7 +206,6 @@ FieldIdTSearcherMap::prepare_term(const DocumentTypeIndexFieldMapT& difm, QueryT const FieldIdTList & index = found->second; if ((find(index.begin(), index.end(), fid) != index.end()) && !seen.contains(qt)) { seen.insert(qt); - auto multi_term = qt->as_multi_term(); if (multi_term != nullptr) { for (auto& subterm : multi_term->get_terms()) { onlyInIndex.emplace_back(subterm.get()); diff --git a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp index 35ce1a07cfb..1dbac859262 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp +++ b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp @@ -223,9 +223,9 @@ FieldSearchSpecMap::buildFieldsInQuery(const Query & query) const query.getLeaves(qtl); for (const auto & term : qtl) { - auto mimt = term->as_multi_index_multi_term(); - if (mimt != nullptr) { - for (const auto& subterm : mimt->get_terms()) { + auto multi_term = term->as_multi_term(); + if (multi_term != nullptr && multi_term->multi_index_terms()) { + for (const auto& subterm : multi_term->get_terms()) { addFieldsFromIndex(subterm->index(), fieldsInQuery); } } else { -- cgit v1.2.3