From 69aae49a30dc657dfa5a603701ffe4ad231ea92f Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Tue, 22 May 2018 21:29:12 +0200 Subject: Refactored to allow iteration over matching elements. --- .../searchcommon/attribute/i_search_context.h | 10 ++-- .../proton/documentmetastore/search_context.cpp | 49 ++++++---------- .../proton/documentmetastore/search_context.h | 16 ++---- .../imported_search_context_test.cpp | 14 ++--- .../vespa/searchlib/attribute/attributeiterators.h | 4 +- .../searchlib/attribute/attributeiterators.hpp | 14 ++--- .../attribute/imported_search_context.cpp | 3 +- .../searchlib/attribute/imported_search_context.h | 14 ++--- .../searchlib/attribute/multinumericattribute.h | 60 +++++++++++--------- .../attribute/multinumericenumattribute.h | 66 ++++++++++++---------- .../searchlib/attribute/multistringattribute.h | 8 +-- .../searchlib/attribute/multistringattribute.hpp | 32 +++++------ .../searchlib/attribute/singlenumericattribute.h | 18 +++--- .../attribute/singlenumericenumattribute.h | 18 +++--- .../attribute/singlesmallnumericattribute.h | 31 +++++----- .../searchlib/attribute/singlestringattribute.h | 9 +-- .../src/vespa/searchlib/attribute/stringbase.cpp | 18 +++--- .../src/vespa/searchlib/attribute/stringbase.h | 21 ++++--- 18 files changed, 202 insertions(+), 203 deletions(-) diff --git a/searchcommon/src/vespa/searchcommon/attribute/i_search_context.h b/searchcommon/src/vespa/searchcommon/attribute/i_search_context.h index 4be1f00dcbc..3eede13c42d 100644 --- a/searchcommon/src/vespa/searchcommon/attribute/i_search_context.h +++ b/searchcommon/src/vespa/searchcommon/attribute/i_search_context.h @@ -24,8 +24,8 @@ public: using DocId = uint32_t; private: - virtual bool onCmp(DocId docId, int32_t &weight) const = 0; - virtual bool onCmp(DocId docId) const = 0; + virtual int32_t onCmp(DocId docId, int32_t elementId, int32_t &weight) const = 0; + virtual int32_t onCmp(DocId docId, int32_t elementId) const = 0; public: virtual ~ISearchContext() {} @@ -57,8 +57,10 @@ public: virtual const QueryTermBase &queryTerm() const = 0; virtual const vespalib::string &attributeName() const = 0; - bool cmp(DocId docId, int32_t &weight) const { return onCmp(docId, weight); } - bool cmp(DocId docId) const { return onCmp(docId); } + int32_t find(DocId docId, int32_t elementId, int32_t &weight) const { return onCmp(docId, elementId, weight); } + int32_t find(DocId docId, int32_t elementId) const { return onCmp(docId, elementId); } + bool matches(DocId docId, int32_t &weight) const { return find(docId, 0, weight) >= 0; } + bool matches(DocId doc) const { return find(doc, 0) >= 0; } }; diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.cpp b/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.cpp index 068b7f4fa00..99865f6bd44 100644 --- a/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.cpp +++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.cpp @@ -12,15 +12,14 @@ using search::QueryTermSimple; using search::fef::TermFieldMatchData; using search::queryeval::SearchIterator; -namespace proton { -namespace documentmetastore { +namespace proton::documentmetastore { namespace { class GidAllSearchIterator : public AttributeIteratorBase { private: - virtual void + void doSeek(uint32_t docId) override { if (_store.validLidFast(docId)) { @@ -28,7 +27,7 @@ private: } } - virtual void + void doUnpack(uint32_t docId) override { _matchData->reset(docId); @@ -37,8 +36,7 @@ private: protected: const DocumentMetaStore & _store; public: - GidAllSearchIterator(TermFieldMatchData *matchData, - const DocumentMetaStore &store) + GidAllSearchIterator(TermFieldMatchData *matchData, const DocumentMetaStore &store) : AttributeIteratorBase(matchData), _store(store) { @@ -79,7 +77,7 @@ class GidSearchIterator : public GidAllSearchIterator private: const GlobalId & _gid; - virtual void + void doSeek(uint32_t docId) override { AttributeVector::DocId lid = 0; @@ -90,9 +88,7 @@ private: } } public: - GidSearchIterator(TermFieldMatchData *matchData, - const DocumentMetaStore &store, - const GlobalId &gid) + GidSearchIterator(TermFieldMatchData *matchData, const DocumentMetaStore &store, const GlobalId &gid) : GidAllSearchIterator(matchData, store), _gid(gid) { @@ -101,23 +97,16 @@ public: } -bool -SearchContext::onCmp(DocId docId, int32_t &weight) const +int32_t +SearchContext::onCmp(DocId, int32_t, int32_t &) const { - (void) docId; - (void) weight; - throw vespalib::IllegalStateException( - "The function is not implemented for documentmetastore::SearchContext"); - return false; + throw vespalib::IllegalStateException("The function is not implemented for documentmetastore::SearchContext"); } -bool -SearchContext::onCmp(DocId docId) const +int32_t +SearchContext::onCmp(DocId, int32_t ) const { - (void) docId; - throw vespalib::IllegalStateException( - "The function is not implemented for documentmetastore::SearchContext"); - return false; + throw vespalib::IllegalStateException("The function is not implemented for documentmetastore::SearchContext"); } unsigned int @@ -127,15 +116,13 @@ SearchContext::approximateHits() const } SearchIterator::UP -SearchContext::createIterator(TermFieldMatchData *matchData, - bool strict) +SearchContext::createIterator(TermFieldMatchData *matchData, bool strict) { return _isWord - ? SearchIterator::UP(new GidSearchIterator(matchData, getStore(), _gid)) + ? std::make_unique(matchData, getStore(), _gid) : strict - ? SearchIterator::UP(new GidStrictAllSearchIterator(matchData, - getStore())) - : SearchIterator::UP(new GidAllSearchIterator(matchData, getStore())); + ? std::make_unique(matchData, getStore()) + : std::make_unique(matchData, getStore()); } const DocumentMetaStore & @@ -144,12 +131,10 @@ SearchContext::getStore() const return static_cast(attribute()); } -SearchContext::SearchContext(QueryTermSimple::UP qTerm, - const DocumentMetaStore &toBeSearched) +SearchContext::SearchContext(QueryTermSimple::UP qTerm, const DocumentMetaStore &toBeSearched) : search::AttributeVector::SearchContext(toBeSearched), _isWord(qTerm->isWord()) { } } -} diff --git a/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.h b/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.h index afd09be43e9..6e1eaa468c9 100644 --- a/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.h +++ b/searchcore/src/vespa/searchcore/proton/documentmetastore/search_context.h @@ -6,8 +6,7 @@ #include #include "documentmetastore.h" -namespace proton { -namespace documentmetastore { +namespace proton::documentmetastore { /** * Search context used to search the document meta store for all valid documents. @@ -15,14 +14,14 @@ namespace documentmetastore { class SearchContext : public search::AttributeVector::SearchContext { private: - typedef search::AttributeVector::DocId DocId; + using DocId = search::AttributeVector::DocId; bool _isWord; document::GlobalId _gid; unsigned int approximateHits() const override; - bool onCmp(DocId docId, int32_t &weight) const override; - bool onCmp(DocId docId) const override; + int32_t onCmp(DocId docId, int32_t elemId, int32_t &weight) const override; + int32_t onCmp(DocId docId, int32_t elemId) const override; search::queryeval::SearchIterator::UP createIterator(search::fef::TermFieldMatchData *matchData, bool strict) override; @@ -30,10 +29,7 @@ private: const DocumentMetaStore &getStore() const; public: - SearchContext(std::unique_ptr qTerm, - const DocumentMetaStore &toBeSearched); + SearchContext(std::unique_ptr qTerm, const DocumentMetaStore &toBeSearched); }; -} // namespace documentmetastore -} // namespace proton - +} diff --git a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp index e8e16ffcc98..bb9d9960d08 100644 --- a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp +++ b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp @@ -303,22 +303,22 @@ TEST_F("Strict iterator handles seek outside of LID space", ArrayValueFixture) { TEST_F("cmp() performs GID mapping and forwards to target attribute", SingleValueFixture) { auto ctx = f.create_context(word_term("5678")); - EXPECT_FALSE(ctx->cmp(DocId(2))); - EXPECT_TRUE(ctx->cmp(DocId(3))); - EXPECT_FALSE(ctx->cmp(DocId(4))); - EXPECT_TRUE(ctx->cmp(DocId(5))); + EXPECT_FALSE(ctx->matches(DocId(2))); + EXPECT_TRUE(ctx->matches(DocId(3))); + EXPECT_FALSE(ctx->matches(DocId(4))); + EXPECT_TRUE(ctx->matches(DocId(5))); } TEST_F("cmp(weight) performs GID mapping and forwards to target attribute", WsetValueFixture) { auto ctx = f.create_context(word_term("foo")); int32_t weight = 0; - EXPECT_FALSE(ctx->cmp(DocId(1), weight)); + EXPECT_FALSE(ctx->matches(DocId(1), weight)); EXPECT_EQUAL(0, weight); // Unchanged - EXPECT_TRUE(ctx->cmp(DocId(2), weight)); + EXPECT_TRUE(ctx->matches(DocId(2), weight)); EXPECT_EQUAL(-5, weight); - EXPECT_TRUE(ctx->cmp(DocId(6), weight)); + EXPECT_TRUE(ctx->matches(DocId(6), weight)); EXPECT_EQUAL(42, weight); } diff --git a/searchlib/src/vespa/searchlib/attribute/attributeiterators.h b/searchlib/src/vespa/searchlib/attribute/attributeiterators.h index febf7d101a9..e0fa06c5e84 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributeiterators.h +++ b/searchlib/src/vespa/searchlib/attribute/attributeiterators.h @@ -82,7 +82,7 @@ protected: public: AttributeIteratorT(const SC &searchContext, fef::TermFieldMatchData *matchData); - bool seekFast(uint32_t docId) const { return _searchContext.cmp(docId); } + bool seekFast(uint32_t docId) const { return _searchContext.matches(docId); } }; template @@ -100,7 +100,7 @@ protected: public: FilterAttributeIteratorT(const SC &searchContext, fef::TermFieldMatchData *matchData); - bool seekFast(uint32_t docId) const { return _searchContext.cmp(docId); } + bool seekFast(uint32_t docId) const { return _searchContext.matches(docId); } }; diff --git a/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp b/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp index fb47ad0cfcc..9b1e837beac 100644 --- a/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp +++ b/searchlib/src/vespa/searchlib/attribute/attributeiterators.hpp @@ -16,14 +16,14 @@ namespace search { template void AttributeIteratorBase::and_hits_into(const SC & sc, BitVector & result, uint32_t begin_id) const { - result.foreach_truebit([&](uint32_t key) { if ( ! sc.cmp(key)) { result.clearBit(key); }}, begin_id); + result.foreach_truebit([&](uint32_t key) { if ( ! sc.matches(key)) { result.clearBit(key); }}, begin_id); result.invalidateCachedCount(); } template void AttributeIteratorBase::or_hits_into(const SC & sc, BitVector & result, uint32_t begin_id) const { - result.foreach_falsebit([&](uint32_t key) { if ( sc.cmp(key)) { result.setBit(key); }}, begin_id); + result.foreach_falsebit([&](uint32_t key) { if ( sc.matches(key)) { result.setBit(key); }}, begin_id); result.invalidateCachedCount(); } @@ -33,7 +33,7 @@ std::unique_ptr AttributeIteratorBase::get_hits(const SC & sc, uint32_t begin_id) const { BitVector::UP result = BitVector::create(begin_id, getEndId()); for (uint32_t docId(std::max(begin_id, getDocId())); docId < getEndId(); docId++) { - if (sc.cmp(docId)) { + if (sc.matches(docId)) { result->setBit(docId); } } @@ -338,7 +338,7 @@ AttributeIteratorT::doSeek(uint32_t docId) { if (isAtEnd(docId)) { setAtEnd(); - } else if (_searchContext.cmp(docId, _weight)) { + } else if (_searchContext.matches(docId, _weight)) { setDocId(docId); } } @@ -349,7 +349,7 @@ FilterAttributeIteratorT::doSeek(uint32_t docId) { if (isAtEnd(docId)) { setAtEnd(); - } else if (_searchContext.cmp(docId)) { + } else if (_searchContext.matches(docId)) { setDocId(docId); } } @@ -359,7 +359,7 @@ void AttributeIteratorStrict::doSeek(uint32_t docId) { for (uint32_t nextId = docId; !isAtEnd(nextId); ++nextId) { - if (_searchContext.cmp(nextId, _weight)) { + if (_searchContext.matches(nextId, _weight)) { setDocId(nextId); return; } @@ -372,7 +372,7 @@ void FilterAttributeIteratorStrict::doSeek(uint32_t docId) { for (uint32_t nextId = docId; !isAtEnd(nextId); ++nextId) { - if (_searchContext.cmp(nextId)) { + if (_searchContext.matches(nextId)) { setDocId(nextId); return; } diff --git a/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp b/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp index bfcd7f29f29..c480eec5e88 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp +++ b/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp @@ -44,8 +44,7 @@ ImportedSearchContext::ImportedSearchContext( } -ImportedSearchContext::~ImportedSearchContext() { -} +ImportedSearchContext::~ImportedSearchContext() = default; unsigned int ImportedSearchContext::approximateHits() const { return _reference_attribute.getNumDocs(); diff --git a/searchlib/src/vespa/searchlib/attribute/imported_search_context.h b/searchlib/src/vespa/searchlib/attribute/imported_search_context.h index f8b434d4c6c..9573139b91a 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_search_context.h +++ b/searchlib/src/vespa/searchlib/attribute/imported_search_context.h @@ -50,7 +50,7 @@ public: const SearchContextParams& params, const ImportedAttributeVector& imported_attribute, const attribute::IAttributeVector &target_attribute); - ~ImportedSearchContext(); + ~ImportedSearchContext() override; std::unique_ptr @@ -64,16 +64,16 @@ public: using DocId = IAttributeVector::DocId; - bool cmp(DocId docId, int32_t& weight) const { - return _target_search_context->cmp(getTargetLid(docId), weight); + int32_t find(DocId docId, int32_t elemId, int32_t& weight) const { + return _target_search_context->find(getTargetLid(docId), elemId, weight); } - bool cmp(DocId docId) const { - return _target_search_context->cmp(getTargetLid(docId)); + int32_t find(DocId docId, int32_t elemId) const { + return _target_search_context->find(getTargetLid(docId), elemId); } - bool onCmp(uint32_t docId, int32_t &weight) const override { return cmp(docId, weight); } - bool onCmp(uint32_t docId) const override { return cmp(docId); } + int32_t onCmp(uint32_t docId, int32_t elemId, int32_t &weight) const override { return find(docId, elemId, weight); } + int32_t onCmp(uint32_t docId, int32_t elemId) const override { return find(docId, elemId); } const ReferenceAttribute& attribute() const noexcept { return _reference_attribute; } diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericattribute.h b/searchlib/src/vespa/searchlib/attribute/multinumericattribute.h index 1e02e4d39b0..a03bc74a44a 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/multinumericattribute.h @@ -71,12 +71,12 @@ public: private: const MultiValueNumericAttribute & _toBeSearched; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elemId) const override { + return find(docId, elemId); } bool valid() const override; @@ -86,25 +86,25 @@ public: Int64Range getAsIntegerTerm() const override; - bool cmp(DocId doc, int32_t & weight) const { + int32_t find(DocId doc, int32_t elemId, int32_t & weight) const { MultiValueArrayRef values(_toBeSearched._mvMapping.get(doc)); - for (const MultiValueType &mv : values) { - if (this->match(mv.value())) { - weight = mv.weight(); - return true; + for (uint32_t i(elemId); i < values.size(); i++) { + if (this->match(values[i].value())) { + weight = values[i].weight(); + return i; } } - return false; + return -1; } - bool cmp(DocId doc) const { + int32_t find(DocId doc, int32_t elemId) const { MultiValueArrayRef values(_toBeSearched._mvMapping.get(doc)); - for (const MultiValueType &mv : values) { - if (this->match(mv.value())) { - return true; + for (uint32_t i(elemId); i < values.size(); i++) { + if (this->match(values[i].value())) { + return i; } } - return false; + return -1; } std::unique_ptr @@ -119,12 +119,12 @@ public: private: const MultiValueNumericAttribute & _toBeSearched; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elemId) const override { + return find(docId, elemId); } protected: @@ -132,27 +132,31 @@ public: public: ArraySearchContext(std::unique_ptr qTerm, const NumericAttribute & toBeSearched); - bool cmp(DocId doc, int32_t & weight) const { + int32_t find(DocId doc, int32_t elemId, int32_t & weight) const { uint32_t hitCount = 0; MultiValueArrayRef values(_toBeSearched._mvMapping.get(doc)); - for (const MultiValueType &mv : values) { - if (this->match(mv.value())) { + int32_t firstMatch = -1; + for (uint32_t i(elemId); i < values.size(); i++) { + if (this->match(values[i].value())) { + if (firstMatch == -1) { + firstMatch = i; + } hitCount++; } } weight = hitCount; - return hitCount != 0; + return firstMatch; } - bool cmp(DocId doc) const { + int32_t find(DocId doc, int32_t elemId) const { MultiValueArrayRef values(_toBeSearched._mvMapping.get(doc)); - for (const MultiValueType &mv : values) { - if (this->match(mv.value())) { - return true; + for (uint32_t i(elemId); i < values.size(); i++) { + if (this->match(values[i].value())) { + return i; } } - return false; + return -1; } Int64Range getAsIntegerTerm() const override; diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.h b/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.h index 66dbbfeb1da..35a81dafb51 100644 --- a/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/multinumericenumattribute.h @@ -52,12 +52,12 @@ protected: protected: const MultiValueNumericEnumAttribute & _toBeSearched; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elemId) const override { + return find(docId, elemId); } bool valid() const override { return this->isValid(); } @@ -65,31 +65,31 @@ protected: public: SetSearchContext(QueryTermSimpleUP qTerm, const NumericAttribute & toBeSearched); - bool - cmp(DocId doc, int32_t & weight) const + int32_t + find(DocId doc, int32_t elemId, int32_t & weight) const { WeightedIndexArrayRef indices(_toBeSearched._mvMapping.get(doc)); - for (const WeightedIndex &wi : indices) { - T v = _toBeSearched._enumStore.getValue(wi.value()); + for (uint32_t i(elemId); i < indices.size(); i++) { + T v = _toBeSearched._enumStore.getValue(indices[i].value()); if (this->match(v)) { - weight = wi.weight(); - return true; + weight = indices[i].weight(); + return elemId; } } - return false; + return -1; } - bool - cmp(DocId doc) const + int32_t + find(DocId doc, int32_t elemId) const { WeightedIndexArrayRef indices(_toBeSearched._mvMapping.get(doc)); - for (const WeightedIndex &wi : indices) { - T v = _toBeSearched._enumStore.getValue(wi.value()); + for (uint32_t i(elemId); i < indices.size(); i++) { + T v = _toBeSearched._enumStore.getValue(indices[i].value()); if (this->match(v)) { - return true; + return i; } } - return false; + return -1; } Int64Range getAsIntegerTerm() const override; @@ -105,12 +105,12 @@ protected: protected: const MultiValueNumericEnumAttribute & _toBeSearched; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elemId) const override { + return find(docId, elemId); } bool valid() const override { return this->isValid(); } @@ -119,34 +119,38 @@ protected: ArraySearchContext(QueryTermSimpleUP qTerm, const NumericAttribute & toBeSearched); Int64Range getAsIntegerTerm() const override; - bool - cmp(DocId doc, int32_t & weight) const + int32_t + find(DocId doc, int32_t elemId, int32_t & weight) const { uint32_t hitCount = 0; WeightedIndexArrayRef indices(_toBeSearched._mvMapping.get(doc)); - for (const WeightedIndex &wi : indices) { - T v = _toBeSearched._enumStore.getValue(wi.value()); + int32_t firstMatch = -1; + for (uint32_t i(elemId); i < indices.size(); i++) { + T v = _toBeSearched._enumStore.getValue(indices[i].value()); if (this->match(v)) { + if (firstMatch == -1) { + firstMatch = i; + } hitCount++; } } weight = hitCount; - return hitCount != 0; + return firstMatch; } bool - cmp(DocId doc) const + find(DocId doc, int32_t elemId) const { WeightedIndexArrayRef indices(_toBeSearched._mvMapping.get(doc)); - for (const WeightedIndex &wi : indices) { - T v = _toBeSearched._enumStore.getValue(wi.value()); + for (uint32_t i(elemId); i < indices.size(); i++) { + T v = _toBeSearched._enumStore.getValue(indices[i].value()); if (this->match(v)) { - return true; + return i; } } - return false; + return -1; } std::unique_ptr diff --git a/searchlib/src/vespa/searchlib/attribute/multistringattribute.h b/searchlib/src/vespa/searchlib/attribute/multistringattribute.h index 7edbcedcb2e..a03a2a02287 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/multistringattribute.h @@ -119,10 +119,10 @@ public: const MultiValueStringAttributeT & myAttribute() const { return static_cast< const MultiValueStringAttributeT & > (attribute()); } - bool onCmp(DocId docId) const override; + int32_t onCmp(DocId docId, int32_t elemId) const override; template - bool collectWeight(DocId doc, int32_t & weight, Collector & collector) const; + int32_t collectWeight(DocId doc, int32_t elemId, int32_t & weight, Collector & collector) const; }; /* @@ -134,7 +134,7 @@ public: StringImplSearchContext(std::move(qTerm), toBeSearched) { } protected: - bool onCmp(DocId docId, int32_t & weight) const override; + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override; }; /* @@ -146,7 +146,7 @@ public: StringImplSearchContext(std::move(qTerm), toBeSearched) { } protected: - bool onCmp(DocId docId, int32_t & weight) const override; + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override; }; template diff --git a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp index a68ac218784..20b9d2ed60b 100644 --- a/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp +++ b/searchlib/src/vespa/searchlib/attribute/multistringattribute.hpp @@ -62,47 +62,47 @@ private: } template -bool -MultiValueStringAttributeT::StringSetImplSearchContext::onCmp(DocId doc, int32_t & weight) const +int32_t +MultiValueStringAttributeT::StringSetImplSearchContext::onCmp(DocId doc, int32_t elemId, int32_t & weight) const { StringAttribute::StringSearchContext::CollectWeight collector; - return this->collectWeight(doc, weight, collector); + return this->collectWeight(doc, elemId, weight, collector); } template -bool -MultiValueStringAttributeT::StringArrayImplSearchContext::onCmp(DocId doc, int32_t & weight) const +int32_t +MultiValueStringAttributeT::StringArrayImplSearchContext::onCmp(DocId doc, int32_t elemId, int32_t & weight) const { StringAttribute::StringSearchContext::CollectHitCount collector; - return this->collectWeight(doc, weight, collector); + return this->collectWeight(doc, elemId, weight, collector); } template template -bool -MultiValueStringAttributeT::StringImplSearchContext::collectWeight(DocId doc, int32_t & weight, Collector & collector) const +int32_t +MultiValueStringAttributeT::StringImplSearchContext::collectWeight(DocId doc, int32_t elemId, int32_t & weight, Collector & collector) const { WeightedIndexArrayRef indices(myAttribute()._mvMapping.get(doc)); EnumAccessor accessor(myAttribute()._enumStore); - collectMatches(indices, accessor, collector); + int32_t foundElem = collectMatches(indices, elemId, accessor, collector); weight = collector.getWeight(); - return collector.hasMatch(); + return foundElem; } template -bool -MultiValueStringAttributeT::StringImplSearchContext::onCmp(DocId doc) const +int32_t +MultiValueStringAttributeT::StringImplSearchContext::onCmp(DocId doc, int32_t elemId) const { const MultiValueStringAttributeT & attr(static_cast< const MultiValueStringAttributeT & > (attribute())); WeightedIndexArrayRef indices(attr._mvMapping.get(doc)); - for (const WeightedIndex &wi : indices) { - if (isMatch(attr._enumStore.getValue(wi.value()))) { - return true; + for (uint32_t i(elemId); i < indices.size(); i++) { + if (isMatch(attr._enumStore.getValue(indices[i].value()))) { + return i; } } - return false; + return -1; } template diff --git a/searchlib/src/vespa/searchlib/attribute/singlenumericattribute.h b/searchlib/src/vespa/searchlib/attribute/singlenumericattribute.h index 8edbf6cde59..de149564f21 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlenumericattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/singlenumericattribute.h @@ -41,27 +41,29 @@ private: private: const T * _data; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int elemId) const override { + return find(docId, elemId); } bool valid() const override; public: SingleSearchContext(std::unique_ptr qTerm, const NumericAttribute & toBeSearched); - bool cmp(DocId docId, int32_t & weight) const { + int32_t find(DocId docId, int32_t elemId, int32_t & weight) const { + if ( elemId != 0) return -1; const T v = _data[docId]; weight = 1; - return this->match(v); + return this->match(v) ? 0 : -1; } - bool cmp(DocId docId) const { + int32_t find(DocId docId, int elemId) const { + if ( elemId != 0) return -1; const T v = _data[docId]; - return this->match(v); + return this->match(v) ? 0 : -1; } Int64Range getAsIntegerTerm() const override; diff --git a/searchlib/src/vespa/searchlib/attribute/singlenumericenumattribute.h b/searchlib/src/vespa/searchlib/attribute/singlenumericenumattribute.h index 7dca10e83e4..f10a6f0f35a 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlenumericenumattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/singlenumericenumattribute.h @@ -58,12 +58,12 @@ protected: protected: const SingleValueNumericEnumAttribute & _toBeSearched; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elemId, int32_t & weight) const override { + return find(docId, elemId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elemId) const override { + return find(docId, elemId); } bool valid() const override; @@ -72,15 +72,17 @@ protected: Int64Range getAsIntegerTerm() const override; - bool cmp(DocId docId, int32_t & weight) const { + int32_t find(DocId docId, int32_t elemId, int32_t & weight) const { + if ( elemId != 0) return -1; T v = _toBeSearched._enumStore.getValue(_toBeSearched.getEnumIndex(docId)); weight = 1; - return this->match(v); + return this->match(v) ? 0 : -1; } - bool cmp(DocId docId) const { + int32_t find(DocId docId, int32_t elemId) const { + if ( elemId != 0) return -1; T v = _toBeSearched._enumStore.getValue(_toBeSearched.getEnumIndex(docId)); - return this->match(v); + return this->match(v) ? 0 : -1; } std::unique_ptr diff --git a/searchlib/src/vespa/searchlib/attribute/singlesmallnumericattribute.h b/searchlib/src/vespa/searchlib/attribute/singlesmallnumericattribute.h index 9320e248160..2087f74d104 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlesmallnumericattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/singlesmallnumericattribute.h @@ -67,12 +67,12 @@ public: uint32_t _valueShiftMask; uint32_t _wordShift; - bool onCmp(DocId docId, int32_t & weight) const override { - return cmp(docId, weight); + int32_t onCmp(DocId docId, int32_t elementId, int32_t & weight) const override { + return cmp(docId, elementId, weight); } - bool onCmp(DocId docId) const override { - return cmp(docId); + int32_t onCmp(DocId docId, int32_t elementId) const override { + return cmp(docId, elementId); } bool valid() const override; @@ -80,19 +80,21 @@ public: public: SingleSearchContext(std::unique_ptr qTerm, const NumericAttribute & toBeSearched); - bool cmp(DocId docId, int32_t & weight) const { + int32_t cmp(DocId docId, int32_t elemId, int32_t & weight) const { + if ( elemId != 0) return -1; const Word &word = _wordData[docId >> _wordShift]; uint32_t valueShift = (docId & _valueShiftMask) << _valueShiftShift; T v = (word >> valueShift) & _valueMask; weight = 1; - return match(v); + return match(v) ? 0 : -1; } - bool cmp(DocId docId) const { + int32_t cmp(DocId docId, int32_t elemId) const { + if ( elemId != 0) return -1; const Word &word = _wordData[docId >> _wordShift]; uint32_t valueShift = (docId & _valueShiftMask) << _valueShiftShift; T v = (word >> valueShift) & _valueMask; - return match(v); + return match(v) ? 0 : -1; } Int64Range getAsIntegerTerm() const override; @@ -101,14 +103,10 @@ public: createFilterIterator(fef::TermFieldMatchData * matchData, bool strict) override; }; - SingleValueSmallNumericAttribute(const vespalib::string & baseFileName, - const Config &c, - Word valueMask, - uint32_t valueShiftShift, - uint32_t valueShiftMask, - uint32_t wordShift); + SingleValueSmallNumericAttribute(const vespalib::string & baseFileName, const Config &c, Word valueMask, + uint32_t valueShiftShift, uint32_t valueShiftMask, uint32_t wordShift); - ~SingleValueSmallNumericAttribute(); + ~SingleValueSmallNumericAttribute() override; uint32_t getValueCount(DocId doc) const override { if (doc >= B::getNumDocs()) { @@ -125,7 +123,8 @@ public: bool onLoad() override; void onSave(IAttributeSaveTarget &saveTarget) override; - SearchContext::UP getSearch(std::unique_ptr term, const attribute::SearchContextParams & params) const override; + SearchContext::UP + getSearch(std::unique_ptr term, const attribute::SearchContextParams & params) const override; T getFast(DocId doc) const { const Word &word = _wordData[doc >> _wordShift]; diff --git a/searchlib/src/vespa/searchlib/attribute/singlestringattribute.h b/searchlib/src/vespa/searchlib/attribute/singlestringattribute.h index 227c1d0667c..8d9fd79717c 100644 --- a/searchlib/src/vespa/searchlib/attribute/singlestringattribute.h +++ b/searchlib/src/vespa/searchlib/attribute/singlestringattribute.h @@ -89,14 +89,15 @@ public: StringSearchContext(std::move(qTerm), toBeSearched) { } protected: - bool onCmp(DocId doc, int32_t & weight) const override { + int32_t onCmp(DocId doc, int32_t elemId, int32_t & weight) const override { weight = 1; - return onCmp(doc); + return onCmp(doc, elemId); } - bool onCmp(DocId doc) const override { + int32_t onCmp(DocId doc, int32_t elemId) const override { + if ( elemId != 0) return -1; const SingleValueStringAttributeT & attr(static_cast &>(attribute())); - return isMatch(attr._enumStore.getValue(attr._enumIndices[doc])); + return isMatch(attr._enumStore.getValue(attr._enumIndices[doc])) ? 0 : -1; } }; diff --git a/searchlib/src/vespa/searchlib/attribute/stringbase.cpp b/searchlib/src/vespa/searchlib/attribute/stringbase.cpp index 5ba936b5f52..3e31c9ca2fa 100644 --- a/searchlib/src/vespa/searchlib/attribute/stringbase.cpp +++ b/searchlib/src/vespa/searchlib/attribute/stringbase.cpp @@ -273,31 +273,31 @@ public: } -bool -StringAttribute::StringSearchContext::onCmp(DocId docId, int32_t & weight) const +int32_t +StringAttribute::StringSearchContext::onCmp(DocId docId, int32_t elemId, int32_t & weight) const { WeightedConstChar * buffer = getBuffer(); uint32_t valueCount = attribute().get(docId, buffer, _bufferLen); CollectWeight collector; DirectAccessor accessor; - collectMatches(vespalib::ConstArrayRef(buffer, std::min(valueCount, _bufferLen)), accessor, collector); + int32_t foundElem = collectMatches(vespalib::ConstArrayRef(buffer, std::min(valueCount, _bufferLen)), elemId, accessor, collector); weight = collector.getWeight(); - return collector.hasMatch(); + return foundElem; } -bool -StringAttribute::StringSearchContext::onCmp(DocId docId) const +int32_t +StringAttribute::StringSearchContext::onCmp(DocId docId, int32_t elemId) const { WeightedConstChar * buffer = getBuffer(); uint32_t valueCount = attribute().get(docId, buffer, _bufferLen); - for (uint32_t i = 0, m = std::min(valueCount, _bufferLen); (i < m); i++) { + for (uint32_t i = elemId, m = std::min(valueCount, _bufferLen); (i < m); i++) { if (isMatch(buffer[i].getValue())) { - return true; + return i; } } - return false; + return -1; } bool StringAttribute::applyWeight(DocId doc, const FieldValue & fv, const ArithmeticValueUpdate & wAdjust) diff --git a/searchlib/src/vespa/searchlib/attribute/stringbase.h b/searchlib/src/vespa/searchlib/attribute/stringbase.h index 5e0847f3039..4176d172ab0 100644 --- a/searchlib/src/vespa/searchlib/attribute/stringbase.h +++ b/searchlib/src/vespa/searchlib/attribute/stringbase.h @@ -96,7 +96,7 @@ private: class StringSearchContext : public SearchContext { public: StringSearchContext(QueryTermSimpleUP qTerm, const StringAttribute & toBeSearched); - virtual ~StringSearchContext(); + ~StringSearchContext() override; private: bool _isPrefix; bool _isRegex; @@ -147,17 +147,22 @@ private: }; template - void collectMatches(vespalib::ConstArrayRef w, const Accessor & ac, Collector & collector) const { - for (const WeightedT &wRef : w) { - if (isMatch(ac.get(wRef.value()))) { - collector.addWeight(wRef.weight()); + int32_t collectMatches(vespalib::ConstArrayRef w, int32_t elemId, const Accessor & ac, Collector & collector) const { + int firstMatch = -1; + for (uint32_t i(elemId); i < w.size(); i++) { + if (isMatch(ac.get(w[i].value()))) { + collector.addWeight(w[i].weight()); + if (firstMatch == -1) { + firstMatch = i; + } } } + return firstMatch; } - bool onCmp(DocId docId, int32_t & weight) const override; - bool onCmp(DocId docId) const override; + int32_t onCmp(DocId docId, int32_t elementId, int32_t & weight) const override; + int32_t onCmp(DocId docId, int32_t elementId) const override; bool isPrefix() const { return _isPrefix; } bool isRegex() const { return _isRegex; } @@ -166,7 +171,7 @@ private: const vespalib::Regexp * getRegex() const { return _regex.get(); } private: WeightedConstChar * getBuffer() const { - if (_buffer == NULL) { + if (_buffer == nullptr) { _buffer = new WeightedConstChar[_bufferLen]; } return _buffer; -- cgit v1.2.3