summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2018-06-06 10:01:52 +0200
committerGitHub <noreply@github.com>2018-06-06 10:01:52 +0200
commitae20ddec12c463d1bbcc7817a8751c7aac355f38 (patch)
tree8204414e27054385d2028cd738608ab999caa08e
parent1e8f8c6492aea894c1f6a2bcd3cf4d5856fcb117 (diff)
Revert "Revert "Balder/sameelement in streaming""
-rw-r--r--document/src/tests/documenttestcase.cpp16
-rw-r--r--document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp9
-rw-r--r--document/src/vespa/document/fieldvalue/iteratorhandler.cpp11
-rw-r--r--document/src/vespa/document/fieldvalue/iteratorhandler.h6
-rw-r--r--document/src/vespa/document/fieldvalue/mapfieldvalue.cpp10
-rw-r--r--searchlib/src/tests/query/query-old.cpp154
-rw-r--r--searchlib/src/vespa/searchlib/query/posocc.h35
-rw-r--r--searchlib/src/vespa/searchlib/query/query.cpp235
-rw-r--r--searchlib/src/vespa/searchlib/query/query.h12
-rw-r--r--searchlib/src/vespa/searchlib/query/querynode.cpp89
-rw-r--r--searchlib/src/vespa/searchlib/query/queryterm.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/query/queryterm.h2
-rw-r--r--vsm/src/vespa/vsm/searcher/fieldsearcher.cpp6
-rw-r--r--vsm/src/vespa/vsm/searcher/fieldsearcher.h4
-rw-r--r--vsm/src/vespa/vsm/vsm/docsumfilter.cpp2
-rw-r--r--vsm/src/vespa/vsm/vsm/docsumfilter.h2
-rw-r--r--vsm/src/vespa/vsm/vsm/vsm-adapter.cpp12
17 files changed, 388 insertions, 227 deletions
diff --git a/document/src/tests/documenttestcase.cpp b/document/src/tests/documenttestcase.cpp
index 33d1a666d4a..ee49259e982 100644
--- a/document/src/tests/documenttestcase.cpp
+++ b/document/src/tests/documenttestcase.cpp
@@ -115,16 +115,22 @@ public:
~Handler();
const std::string & getResult() const { return _result; }
private:
- void onPrimitive(uint32_t, const Content&) override { _result += 'P'; }
+ void onPrimitive(uint32_t, const Content&) override {
+ std::ostringstream os; os << "P-" << getArrayIndex();
+ _result += os.str();
+ }
void onCollectionStart(const Content&) override { _result += '['; }
void onCollectionEnd(const Content&) override { _result += ']'; }
- void onStructStart(const Content&) override { _result += '<'; }
+ void onStructStart(const Content&) override {
+ std::ostringstream os; os << "<" << getArrayIndex() << ":";
+ _result += os.str();
+ }
void onStructEnd(const Content&) override { _result += '>'; }
std::string _result;
};
-Handler::Handler() { }
-Handler::~Handler() { }
+Handler::Handler() = default;
+Handler::~Handler() = default;
void DocumentTest::testTraversing()
@@ -186,7 +192,7 @@ void DocumentTest::testTraversing()
FieldPath empty;
doc.iterateNested(empty.getFullRange(), fullTraverser);
CPPUNIT_ASSERT_EQUAL(fullTraverser.getResult(),
- std::string("<P<P<PP[PPP][<PP><PP>]>>>"));
+ std::string("<0:P-0<0:P-0<0:P-0P-0[P-0P-1P-2][<0:P-0P-0><1:P-1P-1>]>>>"));
}
class VariableIteratorHandler : public IteratorHandler {
diff --git a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
index 194c9b422da..f3239553fa9 100644
--- a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
@@ -37,9 +37,7 @@ ArrayFieldValue::ArrayFieldValue(const ArrayFieldValue& other)
{
}
-ArrayFieldValue::~ArrayFieldValue()
-{
-}
+ArrayFieldValue::~ArrayFieldValue() = default;
ArrayFieldValue&
ArrayFieldValue::operator=(const ArrayFieldValue& other)
@@ -194,6 +192,7 @@ ArrayFieldValue::iterateSubset(int startPos, int endPos,
std::vector<int> indicesToRemove;
for (int i = startPos; i <= endPos && i < static_cast<int>(_array->size()); ++i) {
+ handler.setArrayIndex(i);
if (!variable.empty()) {
handler.getVariables()[variable] = IndexValue(i);
}
@@ -212,9 +211,7 @@ ArrayFieldValue::iterateSubset(int startPos, int endPos,
handler.getVariables().erase(variable);
}
- for (std::vector<int>::reverse_iterator i = indicesToRemove.rbegin();
- i != indicesToRemove.rend(); ++i)
- {
+ for (auto i = indicesToRemove.rbegin(); i != indicesToRemove.rend(); ++i) {
const_cast<ArrayFieldValue&>(*this).remove(*i);
}
diff --git a/document/src/vespa/document/fieldvalue/iteratorhandler.cpp b/document/src/vespa/document/fieldvalue/iteratorhandler.cpp
index 2e9a525d9e6..8764e7908cd 100644
--- a/document/src/vespa/document/fieldvalue/iteratorhandler.cpp
+++ b/document/src/vespa/document/fieldvalue/iteratorhandler.cpp
@@ -5,7 +5,14 @@
namespace document::fieldvalue {
-IteratorHandler::~IteratorHandler() { }
+IteratorHandler::IteratorHandler()
+ : _weight(1),
+ _arrayIndexStack(1, 0),
+ _variables()
+{
+}
+
+IteratorHandler::~IteratorHandler() = default;
void
@@ -18,11 +25,13 @@ IteratorHandler::handleComplex(const FieldValue & fv) {
}
void
IteratorHandler::handleCollectionStart(const FieldValue & fv) {
+ _arrayIndexStack.push_back(0);
onCollectionStart(Content(fv, getWeight()));
}
void
IteratorHandler::handleCollectionEnd(const FieldValue & fv) {
onCollectionEnd(Content(fv, getWeight()));
+ _arrayIndexStack.pop_back();
}
void
IteratorHandler::handleStructStart(const FieldValue & fv) {
diff --git a/document/src/vespa/document/fieldvalue/iteratorhandler.h b/document/src/vespa/document/fieldvalue/iteratorhandler.h
index 757cea54ef9..cf71504e7a1 100644
--- a/document/src/vespa/document/fieldvalue/iteratorhandler.h
+++ b/document/src/vespa/document/fieldvalue/iteratorhandler.h
@@ -4,6 +4,7 @@
#include "variablemap.h"
#include "modificationstatus.h"
+#include <vector>
namespace document::fieldvalue {
@@ -55,7 +56,7 @@ protected:
int _weight;
};
- IteratorHandler() : _weight(1) {}
+ IteratorHandler();
public:
virtual ~IteratorHandler();
@@ -72,6 +73,8 @@ public:
void handleStructStart(const FieldValue &fv);
void handleStructEnd(const FieldValue &fv);
void setWeight(int weight) { _weight = weight; }
+ uint32_t getArrayIndex() const { return _arrayIndexStack.back(); }
+ void setArrayIndex(uint32_t index) { _arrayIndexStack.back() = index; }
ModificationStatus modify(FieldValue &fv) { return doModify(fv); }
fieldvalue::VariableMap &getVariables() { return _variables; }
void setVariables(const fieldvalue::VariableMap &vars) { _variables = vars; }
@@ -93,6 +96,7 @@ private:
int getWeight() const { return _weight; }
int _weight;
+ std::vector<uint32_t> _arrayIndexStack;
fieldvalue::VariableMap _variables;
};
diff --git a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
index 8e5a641ab6e..ebd51c82794 100644
--- a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
@@ -78,9 +78,7 @@ MapFieldValue::MapFieldValue(const DataType &mapType)
{
}
-MapFieldValue::~MapFieldValue()
-{
-}
+MapFieldValue::~MapFieldValue() = default;
MapFieldValue::MapFieldValue(const MapFieldValue & rhs) :
FieldValue(rhs),
@@ -425,6 +423,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
bool wasModified = false;
const bool isWSet(complexFieldValue.inherits(WeightedSetFieldValue::classId));
+ uint32_t index(0);
if ( ! nested.atEnd() ) {
LOG(spam, "not yet at end of field path");
const FieldPathEntry & fpe = nested.cur();
@@ -451,6 +450,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
case FieldPathEntry::MAP_ALL_KEYS:
LOG(spam, "MAP_ALL_KEYS");
for (const auto & entry : *this) {
+ handler.setArrayIndex(index++);
if (isWSet) {
handler.setWeight(static_cast<const IntFieldValue &>(*entry.second).getValue());
}
@@ -462,6 +462,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
case FieldPathEntry::MAP_ALL_VALUES:
LOG(spam, "MAP_ALL_VALUES");
for (const auto & entry : *this) {
+ handler.setArrayIndex(index++);
wasModified = checkAndRemove(*entry.second,
entry.second->iterateNested(nested.next(), handler),
wasModified, keysToRemove);
@@ -482,6 +483,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
} else {
PathRange next = nested.next();
for (const auto & entry : *this) {
+ handler.setArrayIndex(index++);
LOG(spam, "key is '%s'", entry.first->toString().c_str());
handler.getVariables()[fpe.getVariableName()] = IndexValue(*entry.first);
LOG(spam, "vars at this time = %s", handler.getVariables().toString().c_str());
@@ -495,6 +497,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
default:
LOG(spam, "default");
for (const auto & entry : *this) {
+ handler.setArrayIndex(index++);
if (isWSet) {
handler.setWeight(static_cast<const IntFieldValue &>(*entry.second).getValue());
}
@@ -522,6 +525,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
if (handler.handleComplex(complexFieldValue)) {
LOG(spam, "calling handler.handleComplex for all map keys");
for (const auto & entry : *this) {
+ handler.setArrayIndex(index++);
if (isWSet) {
handler.setWeight(static_cast<const IntFieldValue &>(*entry.second).getValue());
}
diff --git a/searchlib/src/tests/query/query-old.cpp b/searchlib/src/tests/query/query-old.cpp
index 77fe813dda5..2cab4447935 100644
--- a/searchlib/src/tests/query/query-old.cpp
+++ b/searchlib/src/tests/query/query-old.cpp
@@ -364,65 +364,63 @@ TEST("testPhraseEvaluate") {
}
// field 0
- terms[0]->add(0, 0, 1);
- terms[1]->add(1, 0, 1);
- terms[2]->add(2, 0, 1);
- terms[0]->add(7, 0, 1);
- terms[1]->add(8, 0, 1);
- terms[2]->add(9, 0, 1);
+ terms[0]->add(0, 0, 0, 1);
+ terms[1]->add(1, 0, 0, 1);
+ terms[2]->add(2, 0, 0, 1);
+ terms[0]->add(7, 0, 0, 1);
+ terms[1]->add(8, 0, 1, 1);
+ terms[2]->add(9, 0, 0, 1);
// field 1
- terms[0]->add(4, 1, 1);
- terms[1]->add(5, 1, 1);
- terms[2]->add(6, 1, 1);
+ terms[0]->add(4, 1, 0, 1);
+ terms[1]->add(5, 1, 0, 1);
+ terms[2]->add(6, 1, 0, 1);
// field 2 (not complete match)
- terms[0]->add(1, 2, 1);
- terms[1]->add(2, 2, 1);
- terms[2]->add(4, 2, 1);
+ terms[0]->add(1, 2, 0, 1);
+ terms[1]->add(2, 2, 0, 1);
+ terms[2]->add(4, 2, 0, 1);
// field 3
- terms[0]->add(0, 3, 1);
- terms[1]->add(1, 3, 1);
- terms[2]->add(2, 3, 1);
+ terms[0]->add(0, 3, 0, 1);
+ terms[1]->add(1, 3, 0, 1);
+ terms[2]->add(2, 3, 0, 1);
// field 4 (not complete match)
- terms[0]->add(1, 4, 1);
- terms[1]->add(2, 4, 1);
+ terms[0]->add(1, 4, 0, 1);
+ terms[1]->add(2, 4, 0, 1);
// field 5 (not complete match)
- terms[0]->add(2, 5, 1);
- terms[1]->add(1, 5, 1);
- terms[2]->add(0, 5, 1);
+ terms[0]->add(2, 5, 0, 1);
+ terms[1]->add(1, 5, 0, 1);
+ terms[2]->add(0, 5, 0, 1);
HitList hits;
PhraseQueryNode * p = static_cast<PhraseQueryNode *>(phrases[0]);
p->evaluateHits(hits);
- ASSERT_TRUE(hits.size() == 4);
+ ASSERT_EQUAL(3u, hits.size());
EXPECT_EQUAL(hits[0].wordpos(), 2u);
EXPECT_EQUAL(hits[0].context(), 0u);
- EXPECT_EQUAL(hits[1].wordpos(), 9u);
- EXPECT_EQUAL(hits[1].context(), 0u);
- EXPECT_EQUAL(hits[2].wordpos(), 6u);
- EXPECT_EQUAL(hits[2].context(), 1u);
- EXPECT_EQUAL(hits[3].wordpos(), 2u);
- EXPECT_EQUAL(hits[3].context(), 3u);
- ASSERT_TRUE(p->getFieldInfoSize() == 4);
+ EXPECT_EQUAL(hits[1].wordpos(), 6u);
+ EXPECT_EQUAL(hits[1].context(), 1u);
+ EXPECT_EQUAL(hits[2].wordpos(), 2u);
+ EXPECT_EQUAL(hits[2].context(), 3u);
+ ASSERT_EQUAL(4u, p->getFieldInfoSize());
EXPECT_EQUAL(p->getFieldInfo(0).getHitOffset(), 0u);
- EXPECT_EQUAL(p->getFieldInfo(0).getHitCount(), 2u);
- EXPECT_EQUAL(p->getFieldInfo(1).getHitOffset(), 2u);
+ EXPECT_EQUAL(p->getFieldInfo(0).getHitCount(), 1u);
+ EXPECT_EQUAL(p->getFieldInfo(1).getHitOffset(), 1u);
EXPECT_EQUAL(p->getFieldInfo(1).getHitCount(), 1u);
EXPECT_EQUAL(p->getFieldInfo(2).getHitOffset(), 0u); // invalid, but will never be used
EXPECT_EQUAL(p->getFieldInfo(2).getHitCount(), 0u);
- EXPECT_EQUAL(p->getFieldInfo(3).getHitOffset(), 3u);
+ EXPECT_EQUAL(p->getFieldInfo(3).getHitOffset(), 2u);
EXPECT_EQUAL(p->getFieldInfo(3).getHitCount(), 1u);
}
TEST("testHit") {
// positions (0 - (2^24-1))
- assertHit(Hit(0, 0, 0), 0, 0, 0);
- assertHit(Hit(256, 0, 1), 256, 0, 1);
- assertHit(Hit(16777215, 0, -1), 16777215, 0, -1);
- assertHit(Hit(16777216, 0, 1), 0, 1, 1); // overflow
+ assertHit(Hit(0, 0, 0, 0), 0, 0, 0);
+ assertHit(Hit(256, 0, 0, 1), 256, 0, 1);
+ assertHit(Hit(16777215, 0, 0, -1), 16777215, 0, -1);
+ assertHit(Hit(16777216, 0, 0, 1), 0, 1, 1); // overflow
// contexts (0 - 255)
- assertHit(Hit(0, 1, 1), 0, 1, 1);
- assertHit(Hit(0, 255, 1), 0, 255, 1);
- assertHit(Hit(0, 256, 1), 0, 0, 1); // overflow
+ assertHit(Hit(0, 1, 0, 1), 0, 1, 1);
+ assertHit(Hit(0, 255, 0, 1), 0, 255, 1);
+ assertHit(Hit(0, 256, 0, 1), 0, 0, 1); // overflow
}
void assertInt8Range(const std::string &term, bool expAdjusted, int64_t expLow, int64_t expHigh) {
@@ -653,4 +651,84 @@ TEST("require that we do not break the stack on bad query") {
EXPECT_FALSE(term.isValid());
}
+namespace {
+ void verifyQueryTermNode(const vespalib::string & index, const QueryNode *node) {
+ EXPECT_TRUE(dynamic_cast<const QueryTerm *>(node) != nullptr);
+ EXPECT_EQUAL(index, node->getIndex());
+ }
+}
+TEST("testSameElementEvaluate") {
+ QueryBuilder<SimpleQueryNodeTypes> builder;
+ builder.addSameElement(3, "field");
+ {
+ builder.addStringTerm("a", "f1", 0, Weight(0));
+ builder.addStringTerm("b", "f2", 1, Weight(0));
+ builder.addStringTerm("c", "f3", 2, Weight(0));
+ }
+ Node::UP node = builder.build();
+ vespalib::string stackDump = StackDumpCreator::create(*node);
+ QueryNodeResultFactory empty;
+ Query q(empty, stackDump);
+ SameElementQueryNode * sameElem = dynamic_cast<SameElementQueryNode *>(&q.getRoot());
+ EXPECT_TRUE(sameElem != nullptr);
+ EXPECT_EQUAL("field", sameElem->getIndex());
+ EXPECT_EQUAL(3u, sameElem->size());
+ verifyQueryTermNode("field.f1", (*sameElem)[0].get());
+ verifyQueryTermNode("field.f2", (*sameElem)[1].get());
+ verifyQueryTermNode("field.f3", (*sameElem)[2].get());
+
+ QueryTermList terms;
+ q.getLeafs(terms);
+ EXPECT_EQUAL(3u, terms.size());
+ for (QueryTerm * qt : terms) {
+ qt->resizeFieldId(3);
+ }
+
+ // field 0
+ terms[0]->add(1, 0, 0, 10);
+ terms[0]->add(2, 0, 1, 20);
+ terms[0]->add(3, 0, 2, 30);
+ terms[0]->add(4, 0, 3, 40);
+ terms[0]->add(5, 0, 4, 50);
+ terms[0]->add(6, 0, 5, 60);
+
+ terms[1]->add(7, 1, 0, 70);
+ terms[1]->add(8, 1, 1, 80);
+ terms[1]->add(9, 1, 2, 90);
+ terms[1]->add(10, 1, 4, 100);
+ terms[1]->add(11, 1, 5, 110);
+ terms[1]->add(12, 1, 6, 120);
+
+ terms[2]->add(13, 2, 0, 130);
+ terms[2]->add(14, 2, 2, 140);
+ terms[2]->add(15, 2, 4, 150);
+ terms[2]->add(16, 2, 5, 160);
+ terms[2]->add(17, 2, 6, 170);
+ HitList hits;
+
+ sameElem->evaluateHits(hits);
+ EXPECT_EQUAL(4u, hits.size());
+ EXPECT_EQUAL(0u, hits[0].wordpos());
+ EXPECT_EQUAL(2u, hits[0].context());
+ EXPECT_EQUAL(0u, hits[0].elemId());
+ EXPECT_EQUAL(130, hits[0].weight());
+
+ EXPECT_EQUAL(0u, hits[1].wordpos());
+ EXPECT_EQUAL(2u, hits[1].context());
+ EXPECT_EQUAL(2u, hits[1].elemId());
+ EXPECT_EQUAL(140, hits[1].weight());
+
+ EXPECT_EQUAL(0u, hits[2].wordpos());
+ EXPECT_EQUAL(2u, hits[2].context());
+ EXPECT_EQUAL(4u, hits[2].elemId());
+ EXPECT_EQUAL(150, hits[2].weight());
+
+ EXPECT_EQUAL(0u, hits[3].wordpos());
+ EXPECT_EQUAL(2u, hits[3].context());
+ EXPECT_EQUAL(5u, hits[3].elemId());
+ EXPECT_EQUAL(160, hits[3].weight());
+
+}
+
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/vespa/searchlib/query/posocc.h b/searchlib/src/vespa/searchlib/query/posocc.h
index 1b5b6283f88..fcabef0297f 100644
--- a/searchlib/src/vespa/searchlib/query/posocc.h
+++ b/searchlib/src/vespa/searchlib/query/posocc.h
@@ -4,28 +4,29 @@
#include <cstdint>
#include <vector>
-namespace search
-{
+namespace search {
class Hit
{
- public:
- Hit(uint32_t pos_, uint32_t context_, int32_t weight_) :
- _position(pos_ | (context_<<24)),
- _weight(weight_)
- { }
- int32_t weight() const { return _weight; }
- uint32_t pos() const { return _position; }
- uint32_t wordpos() const { return _position & 0xffffff; }
- uint32_t context() const { return _position >> 24; }
- bool operator < (const Hit & b) const { return cmp(b) < 0; }
- private:
- int cmp(const Hit & b) const { return _position - b._position; }
- uint32_t _position;
- int32_t _weight;
+public:
+ Hit(uint32_t pos_, uint32_t context_, uint32_t elemId_, int32_t weight_)
+ : _position(pos_ | (context_<<24)),
+ _elemId(elemId_),
+ _weight(weight_)
+ { }
+ int32_t weight() const { return _weight; }
+ uint32_t pos() const { return _position; }
+ uint32_t wordpos() const { return _position & 0xffffff; }
+ uint32_t context() const { return _position >> 24; }
+ uint32_t elemId() const { return _elemId; }
+ bool operator < (const Hit & b) const { return cmp(b) < 0; }
+private:
+ int cmp(const Hit & b) const { return _position - b._position; }
+ uint32_t _position;
+ uint32_t _elemId;
+ int32_t _weight;
};
typedef std::vector<Hit> HitList;
}
-
diff --git a/searchlib/src/vespa/searchlib/query/query.cpp b/searchlib/src/vespa/searchlib/query/query.cpp
index 984337f40ba..659e48a0662 100644
--- a/searchlib/src/vespa/searchlib/query/query.cpp
+++ b/searchlib/src/vespa/searchlib/query/query.cpp
@@ -16,97 +16,90 @@ QueryConnector::QueryConnector(const char * opName) :
{
}
-QueryConnector::~QueryConnector() { }
+QueryConnector::~QueryConnector() = default;
const HitList & QueryConnector::evaluateHits(HitList & hl) const
{
- if (evaluate()) {
- hl.push_back(Hit(1, 0, 1));
- }
- return hl;
+ if (evaluate()) {
+ hl.push_back(Hit(1, 0, 0, 1));
+ }
+ return hl;
}
void QueryConnector::reset()
{
- for(iterator it=begin(), mt=end(); it != mt; it++) {
- QueryNode & qn = **it;
- qn.reset();
- }
+ for(const auto & node : *this) {
+ node->reset();
+ }
}
void QueryConnector::getLeafs(QueryTermList & tl)
{
- for(iterator it=begin(), mt=end(); it != mt; it++) {
- QueryNode & qn = **it;
- qn.getLeafs(tl);
- }
+ for(const auto & node : *this) {
+ node->getLeafs(tl);
+ }
}
void QueryConnector::getLeafs(ConstQueryTermList & tl) const
{
- for(const_iterator it=begin(), mt=end(); it != mt; it++) {
- const QueryNode & qn = **it;
- qn.getLeafs(tl);
- }
+ for(const auto & node : *this) {
+ node->getLeafs(tl);
+ }
}
void QueryConnector::getPhrases(QueryNodeRefList & tl)
{
- for(iterator it=begin(), mt=end(); it != mt; it++) {
- QueryNode & qn = **it;
- qn.getPhrases(tl);
- }
+ for(const auto & node : *this) {
+ node->getPhrases(tl);
+ }
}
void QueryConnector::getPhrases(ConstQueryNodeRefList & tl) const
{
- for(const_iterator it=begin(), mt=end(); it != mt; it++) {
- const QueryNode & qn = **it;
- qn.getPhrases(tl);
- }
+ for(const auto & node : *this) {
+ node->getPhrases(tl);
+ }
}
size_t QueryConnector::depth() const
{
- size_t d(0);
- for(const_iterator it=begin(), mt=end(); (it!=mt); it++) {
- const QueryNode & qn = **it;
- size_t t = qn.depth();
- if (t > d)
- d = t;
- }
- return d+1;
+ size_t d(0);
+ for(const auto & node : *this) {
+ size_t t = node->depth();
+ if (t > d) {
+ d = t;
+ }
+ }
+ return d+1;
}
size_t QueryConnector::width() const
{
size_t w(0);
- for(const_iterator it=begin(), mt=end(); (it!=mt); it++) {
- const QueryNode & qn = **it;
- w += qn.width();
+ for(const auto & node : *this) {
+ w += node->width();
}
return w;
}
-QueryConnector *
+std::unique_ptr<QueryConnector>
QueryConnector::create(ParseItem::ItemType type)
{
switch (type) {
- case search::ParseItem::ITEM_AND: return new AndQueryNode();
- case search::ParseItem::ITEM_OR: return new OrQueryNode();
- case search::ParseItem::ITEM_WEAK_AND: return new OrQueryNode();
- case search::ParseItem::ITEM_EQUIV: return new EquivQueryNode();
- case search::ParseItem::ITEM_WEIGHTED_SET: return new EquivQueryNode();
- case search::ParseItem::ITEM_DOT_PRODUCT: return new OrQueryNode();
- case search::ParseItem::ITEM_WAND: return new OrQueryNode();
- case search::ParseItem::ITEM_NOT: return new AndNotQueryNode();
- case search::ParseItem::ITEM_PHRASE: return new PhraseQueryNode();
- case search::ParseItem::ITEM_SAME_ELEMENT: return new AndQueryNode(); // TODO: This needs a same element operation to work for streaming search too.
- case search::ParseItem::ITEM_NEAR: return new NearQueryNode();
- case search::ParseItem::ITEM_ONEAR: return new ONearQueryNode();
- default:
- return nullptr;
+ case search::ParseItem::ITEM_AND: return std::make_unique<AndQueryNode>();
+ case search::ParseItem::ITEM_OR: return std::make_unique<OrQueryNode>();
+ case search::ParseItem::ITEM_WEAK_AND: return std::make_unique<OrQueryNode>();
+ case search::ParseItem::ITEM_EQUIV: return std::make_unique<EquivQueryNode>();
+ case search::ParseItem::ITEM_WEIGHTED_SET: return std::make_unique<EquivQueryNode>();
+ case search::ParseItem::ITEM_DOT_PRODUCT: return std::make_unique<OrQueryNode>();
+ case search::ParseItem::ITEM_WAND: return std::make_unique<OrQueryNode>();
+ case search::ParseItem::ITEM_NOT: return std::make_unique<AndNotQueryNode>();
+ case search::ParseItem::ITEM_PHRASE: return std::make_unique<PhraseQueryNode>();
+ case search::ParseItem::ITEM_SAME_ELEMENT: return std::make_unique<SameElementQueryNode>();
+ case search::ParseItem::ITEM_NEAR: return std::make_unique<NearQueryNode>();
+ case search::ParseItem::ITEM_ONEAR: return std::make_unique<ONearQueryNode>();
+ default: return nullptr;
}
}
@@ -153,61 +146,116 @@ bool EquivQueryNode::evaluate() const
return OrQueryNode::evaluate();
}
+bool SameElementQueryNode::evaluate() const {
+ HitList hl;
+ return evaluateHits(hl).empty();
+}
+
+const HitList &
+SameElementQueryNode::evaluateHits(HitList & hl) const
+{
+ hl.clear();
+ if ( !AndQueryNode::evaluate()) return hl;
+
+ HitList tmpHL;
+ unsigned int numFields = size();
+ unsigned int currMatchCount = 0;
+ std::vector<unsigned int> indexVector(numFields, 0);
+ auto curr = static_cast<const QueryTerm *> ((*this)[currMatchCount].get());
+ bool exhausted( curr->evaluateHits(tmpHL).empty());
+ for (; !exhausted; ) {
+ auto next = static_cast<const QueryTerm *>((*this)[currMatchCount+1].get());
+ unsigned int & currIndex = indexVector[currMatchCount];
+ unsigned int & nextIndex = indexVector[currMatchCount+1];
+
+ const auto & currHit = curr->evaluateHits(tmpHL)[currIndex];
+ uint32_t currElemId = currHit.elemId();
+
+ const HitList & nextHL = next->evaluateHits(tmpHL);
+
+ size_t nextIndexMax = nextHL.size();
+ while ((nextIndex < nextIndexMax) && (nextHL[nextIndex].elemId() < currElemId)) {
+ nextIndex++;
+ }
+ if (nextHL[nextIndex].elemId() == currElemId) {
+ currMatchCount++;
+ if ((currMatchCount+1) == numFields) {
+ Hit h = nextHL[indexVector[currMatchCount]];
+ hl.emplace_back(0, h.context(), h.elemId(), h.weight());
+ currMatchCount = 0;
+ indexVector[0]++;
+ }
+ } else {
+ currMatchCount = 0;
+ indexVector[currMatchCount]++;
+ }
+ curr = static_cast<const QueryTerm *>((*this)[currMatchCount].get());
+ exhausted = (nextIndex >= nextIndexMax) || (indexVector[currMatchCount] >= curr->evaluateHits(tmpHL).size());
+ }
+ return hl;
+}
bool PhraseQueryNode::evaluate() const
{
- bool ok(false);
HitList hl;
- ok = ! evaluateHits(hl).empty();
- return ok;
+ return evaluateHits(hl).empty();
}
void PhraseQueryNode::getPhrases(QueryNodeRefList & tl) { tl.push_back(this); }
void PhraseQueryNode::getPhrases(ConstQueryNodeRefList & tl) const { tl.push_back(this); }
-const HitList & PhraseQueryNode::evaluateHits(HitList & hl) const
+const HitList &
+PhraseQueryNode::evaluateHits(HitList & hl) const
{
- hl.clear();
- _fieldInfo.clear();
- bool andResult(AndQueryNode::evaluate());
- if (andResult) {
+ hl.clear();
+ _fieldInfo.clear();
+ if ( ! AndQueryNode::evaluate()) return hl;
+
HitList tmpHL;
unsigned int fullPhraseLen = size();
unsigned int currPhraseLen = 0;
std::vector<unsigned int> indexVector(fullPhraseLen, 0);
- const QueryTerm * curr = static_cast<const QueryTerm *> (&(*(*this)[currPhraseLen]));
+ auto curr = static_cast<const QueryTerm *> ((*this)[currPhraseLen].get());
bool exhausted( curr->evaluateHits(tmpHL).empty());
for (; !exhausted; ) {
- const QueryTerm & next = static_cast<const QueryTerm &>(*(*this)[currPhraseLen+1]);
- unsigned int & currIndex = indexVector[currPhraseLen];
- unsigned int & nextIndex = indexVector[currPhraseLen+1];
- const HitList & nextHL = next.evaluateHits(tmpHL);
-
- size_t firstPosition = curr->evaluateHits(tmpHL)[currIndex].pos();
- int diff(0);
- size_t nextIndexMax = nextHL.size();
- while ((nextIndex < nextIndexMax) && ((diff = nextHL[nextIndex].pos()-firstPosition) < 1))
- nextIndex++;
- if (diff == 1) {
- currPhraseLen++;
- bool ok = ((currPhraseLen+1)==fullPhraseLen);
- if (ok) {
- Hit h = nextHL[indexVector[currPhraseLen]];
- hl.push_back(h);
- const QueryTerm::FieldInfo & fi = next.getFieldInfo(h.context());
- updateFieldInfo(h.context(), hl.size() - 1, fi.getFieldLength());
- currPhraseLen = 0;
- indexVector[0]++;
+ auto next = static_cast<const QueryTerm *>((*this)[currPhraseLen+1].get());
+ unsigned int & currIndex = indexVector[currPhraseLen];
+ unsigned int & nextIndex = indexVector[currPhraseLen+1];
+
+ const auto & currHit = curr->evaluateHits(tmpHL)[currIndex];
+ size_t firstPosition = currHit.pos();
+ uint32_t currElemId = currHit.elemId();
+ uint32_t currContext = currHit.context();
+
+ const HitList & nextHL = next->evaluateHits(tmpHL);
+
+ int diff(0);
+ size_t nextIndexMax = nextHL.size();
+ while ((nextIndex < nextIndexMax) &&
+ ((nextHL[nextIndex].context() < currContext) ||
+ ((nextHL[nextIndex].context() == currContext) && (nextHL[nextIndex].elemId() <= currElemId))) &&
+ ((diff = nextHL[nextIndex].pos()-firstPosition) < 1))
+ {
+ nextIndex++;
+ }
+ if ((diff == 1) && (nextHL[nextIndex].context() == currContext) && (nextHL[nextIndex].elemId() == currElemId)) {
+ currPhraseLen++;
+ if ((currPhraseLen+1) == fullPhraseLen) {
+ Hit h = nextHL[indexVector[currPhraseLen]];
+ hl.push_back(h);
+ const QueryTerm::FieldInfo & fi = next->getFieldInfo(h.context());
+ updateFieldInfo(h.context(), hl.size() - 1, fi.getFieldLength());
+ currPhraseLen = 0;
+ indexVector[0]++;
+ }
+ } else {
+ currPhraseLen = 0;
+ indexVector[currPhraseLen]++;
}
- } else {
- currPhraseLen = 0;
- indexVector[currPhraseLen]++;
- }
- curr = static_cast<const QueryTerm *>(&*(*this)[currPhraseLen]);
- exhausted = (nextIndex >= nextIndexMax) || (indexVector[currPhraseLen] >= curr->evaluateHits(tmpHL).size());
+ curr = static_cast<const QueryTerm *>((*this)[currPhraseLen].get());
+ exhausted = (nextIndex >= nextIndexMax) || (indexVector[currPhraseLen] >= curr->evaluateHits(tmpHL).size());
}
- }
- return hl;
+ return hl;
}
void
@@ -227,9 +275,8 @@ PhraseQueryNode::updateFieldInfo(size_t fid, size_t offset, size_t fieldLength)
bool NotQueryNode::evaluate() const
{
bool ok(false);
- for (const_iterator it=begin(), mt=end(); it!=mt; it++) {
- const QueryNode & qn = **it;
- ok |= ! qn.evaluate();
+ for (const auto & node : *this) {
+ ok |= ! node->evaluate();
}
return ok;
}
@@ -253,9 +300,7 @@ bool ONearQueryNode::evaluate() const
return ok;
}
-Query::Query() :
- _root()
-{ }
+Query::Query() = default;
Query::Query(const QueryNodeResultFactory & factory, const QueryPacketT & queryRep) :
_root()
@@ -273,7 +318,7 @@ bool Query::build(const QueryNodeResultFactory & factory, const QueryPacketT & q
{
search::SimpleQueryStackDumpIterator stack(queryRep);
if (stack.next()) {
- _root.reset(QueryNode::Build(NULL, factory, stack, true).release());
+ _root = QueryNode::Build(nullptr, factory, stack, true);
}
return valid();
}
diff --git a/searchlib/src/vespa/searchlib/query/query.h b/searchlib/src/vespa/searchlib/query/query.h
index 9bb1b29aae5..b9bcd76d869 100644
--- a/searchlib/src/vespa/searchlib/query/query.h
+++ b/searchlib/src/vespa/searchlib/query/query.h
@@ -28,7 +28,7 @@ public:
virtual void visitMembers(vespalib::ObjectVisitor &visitor) const;
void setIndex(const vespalib::string & index) override { _index = index; }
const vespalib::string & getIndex() const override { return _index; }
- static QueryConnector * create(ParseItem::ItemType type);
+ static std::unique_ptr<QueryConnector> create(ParseItem::ItemType type);
virtual bool isFlattenable(ParseItem::ItemType type) const { (void) type; return false; }
private:
vespalib::string _opName;
@@ -123,6 +123,15 @@ private:
#endif
};
+class SameElementQueryNode : public AndQueryNode
+{
+public:
+ SameElementQueryNode() : AndQueryNode("SAME_ELEMENT") { }
+ bool evaluate() const override;
+ const HitList & evaluateHits(HitList & hl) const override;
+ bool isFlattenable(ParseItem::ItemType type) const override { return type == ParseItem::ITEM_NOT; }
+};
+
/**
Unary Not operator. Just inverts the nodes result.
*/
@@ -190,6 +199,7 @@ public:
size_t width() const;
bool valid() const { return _root.get() != NULL; }
const QueryNode & getRoot() const { return *_root; }
+ QueryNode & getRoot() { return *_root; }
static QueryNode::UP steal(Query && query) { return std::move(query._root); }
private:
QueryNode::UP _root;
diff --git a/searchlib/src/vespa/searchlib/query/querynode.cpp b/searchlib/src/vespa/searchlib/query/querynode.cpp
index 0d0a06de7af..fcc539658d0 100644
--- a/searchlib/src/vespa/searchlib/query/querynode.cpp
+++ b/searchlib/src/vespa/searchlib/query/querynode.cpp
@@ -9,38 +9,44 @@ namespace search {
namespace {
vespalib::stringref DEFAULT("default");
+ bool isPhraseOrNear(const QueryNode * qn) {
+ return dynamic_cast<const NearQueryNode *> (qn) || dynamic_cast<const PhraseQueryNode *> (qn);
+ }
}
-QueryNode::UP QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factory, search::SimpleQueryStackDumpIterator & queryRep, bool allowRewrite)
+QueryNode::UP
+QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factory,
+ SimpleQueryStackDumpIterator & queryRep, bool allowRewrite)
{
unsigned int arity = queryRep.getArity();
- search::ParseItem::ItemType type = queryRep.getType();
+ ParseItem::ItemType type = queryRep.getType();
UP qn;
switch (type) {
- case search::ParseItem::ITEM_AND:
- case search::ParseItem::ITEM_OR:
- case search::ParseItem::ITEM_WEAK_AND:
- case search::ParseItem::ITEM_EQUIV:
- case search::ParseItem::ITEM_WEIGHTED_SET:
- case search::ParseItem::ITEM_DOT_PRODUCT:
- case search::ParseItem::ITEM_WAND:
- case search::ParseItem::ITEM_NOT:
- case search::ParseItem::ITEM_PHRASE:
- case search::ParseItem::ITEM_SAME_ELEMENT:
- case search::ParseItem::ITEM_NEAR:
- case search::ParseItem::ITEM_ONEAR:
+ case ParseItem::ITEM_AND:
+ case ParseItem::ITEM_OR:
+ case ParseItem::ITEM_WEAK_AND:
+ case ParseItem::ITEM_EQUIV:
+ case ParseItem::ITEM_WEIGHTED_SET:
+ case ParseItem::ITEM_DOT_PRODUCT:
+ case ParseItem::ITEM_WAND:
+ case ParseItem::ITEM_NOT:
+ case ParseItem::ITEM_PHRASE:
+ case ParseItem::ITEM_SAME_ELEMENT:
+ case ParseItem::ITEM_NEAR:
+ case ParseItem::ITEM_ONEAR:
{
- qn.reset(QueryConnector::create(type));
- if (qn.get()) {
+ qn = QueryConnector::create(type);
+ if (qn) {
QueryConnector * qc = dynamic_cast<QueryConnector *> (qn.get());
NearQueryNode * nqn = dynamic_cast<NearQueryNode *> (qc);
if (nqn) {
nqn->distance(queryRep.getArg1());
}
- if ((type == search::ParseItem::ITEM_WEAK_AND) ||
- (type == search::ParseItem::ITEM_WEIGHTED_SET) ||
- (type == search::ParseItem::ITEM_DOT_PRODUCT) ||
- (type == search::ParseItem::ITEM_WAND))
+ if ((type == ParseItem::ITEM_WEAK_AND) ||
+ (type == ParseItem::ITEM_WEIGHTED_SET) ||
+ (type == ParseItem::ITEM_DOT_PRODUCT) ||
+ (type == ParseItem::ITEM_SAME_ELEMENT) ||
+ (type == ParseItem::ITEM_WAND))
{
qn->setIndex(queryRep.getIndexName());
}
@@ -49,48 +55,50 @@ QueryNode::UP QueryNode::Build(const QueryNode * parent, const QueryNodeResultFa
if (qc->isFlattenable(queryRep.getType())) {
arity += queryRep.getArity();
} else {
- UP child(Build(qc, factory, queryRep,
- allowRewrite && ((dynamic_cast<NearQueryNode *> (qn.get()) == NULL) && (dynamic_cast<PhraseQueryNode *> (qn.get()) == NULL))));
+ UP child = Build(qc, factory, queryRep, allowRewrite && !isPhraseOrNear(qn.get()));
qc->push_back(std::move(child));
}
}
}
}
break;
- case search::ParseItem::ITEM_NUMTERM:
- case search::ParseItem::ITEM_TERM:
- case search::ParseItem::ITEM_PREFIXTERM:
- case search::ParseItem::ITEM_REGEXP:
- case search::ParseItem::ITEM_SUBSTRINGTERM:
- case search::ParseItem::ITEM_EXACTSTRINGTERM:
- case search::ParseItem::ITEM_SUFFIXTERM:
- case search::ParseItem::ITEM_PURE_WEIGHTED_STRING:
- case search::ParseItem::ITEM_PURE_WEIGHTED_LONG:
+ case ParseItem::ITEM_NUMTERM:
+ case ParseItem::ITEM_TERM:
+ case ParseItem::ITEM_PREFIXTERM:
+ case ParseItem::ITEM_REGEXP:
+ case ParseItem::ITEM_SUBSTRINGTERM:
+ case ParseItem::ITEM_EXACTSTRINGTERM:
+ case ParseItem::ITEM_SUFFIXTERM:
+ case ParseItem::ITEM_PURE_WEIGHTED_STRING:
+ case ParseItem::ITEM_PURE_WEIGHTED_LONG:
{
- vespalib::stringref index = queryRep.getIndexName();
+ vespalib::string index = queryRep.getIndexName();
if (index.empty()) {
- if ((type == search::ParseItem::ITEM_PURE_WEIGHTED_STRING) || (type == search::ParseItem::ITEM_PURE_WEIGHTED_LONG)) {
+ if ((type == ParseItem::ITEM_PURE_WEIGHTED_STRING) || (type == ParseItem::ITEM_PURE_WEIGHTED_LONG)) {
index = parent->getIndex();
} else {
index = DEFAULT;
}
}
+ if (dynamic_cast<const SameElementQueryNode *>(parent) != nullptr) {
+ index = parent->getIndex() + "." + index;
+ }
vespalib::stringref term = queryRep.getTerm();
QueryTerm::SearchTerm sTerm(QueryTerm::WORD);
switch (type) {
- case search::ParseItem::ITEM_REGEXP:
+ case ParseItem::ITEM_REGEXP:
sTerm = QueryTerm::REGEXP;
break;
- case search::ParseItem::ITEM_PREFIXTERM:
+ case ParseItem::ITEM_PREFIXTERM:
sTerm = QueryTerm::PREFIXTERM;
break;
- case search::ParseItem::ITEM_SUBSTRINGTERM:
+ case ParseItem::ITEM_SUBSTRINGTERM:
sTerm = QueryTerm::SUBSTRINGTERM;
break;
- case search::ParseItem::ITEM_EXACTSTRINGTERM:
+ case ParseItem::ITEM_EXACTSTRINGTERM:
sTerm = QueryTerm::EXACTSTRINGTERM;
break;
- case search::ParseItem::ITEM_SUFFIXTERM:
+ case ParseItem::ITEM_SUFFIXTERM:
sTerm = QueryTerm::SUFFIXTERM;
break;
default:
@@ -107,10 +115,9 @@ QueryNode::UP QueryNode::Build(const QueryNode * parent, const QueryNodeResultFa
qt->setWeight(queryRep.GetWeight());
qt->setUniqueId(queryRep.getUniqueId());
if ( qt->encoding().isBase10Integer() || ! qt->encoding().isFloat() || ! factory.getRewriteFloatTerms() || !allowRewrite || (ssTerm.find('.') == vespalib::string::npos)) {
- qn.reset(qt.release());
+ qn = std::move(qt);
} else {
std::unique_ptr<PhraseQueryNode> phrase(new PhraseQueryNode());
-
phrase->push_back(UP(new QueryTerm(factory.create(), ssTerm.substr(0, ssTerm.find('.')), ssIndex, QueryTerm::WORD)));
phrase->push_back(UP(new QueryTerm(factory.create(), ssTerm.substr(ssTerm.find('.') + 1), ssIndex, QueryTerm::WORD)));
std::unique_ptr<EquivQueryNode> orqn(new EquivQueryNode());
@@ -121,7 +128,7 @@ QueryNode::UP QueryNode::Build(const QueryNode * parent, const QueryNodeResultFa
}
}
break;
- case search::ParseItem::ITEM_RANK:
+ case ParseItem::ITEM_RANK:
{
if (arity >= 1) {
queryRep.next();
diff --git a/searchlib/src/vespa/searchlib/query/queryterm.cpp b/searchlib/src/vespa/searchlib/query/queryterm.cpp
index d47d942dc10..ee2e72b41a8 100644
--- a/searchlib/src/vespa/searchlib/query/queryterm.cpp
+++ b/searchlib/src/vespa/searchlib/query/queryterm.cpp
@@ -73,7 +73,7 @@ QueryTermBase::QueryTermBase() :
_termUCS4.push_back(0);
}
-QueryTermBase::~QueryTermBase() { }
+QueryTermBase::~QueryTermBase() = default;
QueryTermBase::QueryTermBase(const string & termS, SearchTerm type) :
QueryTermSimple(termS, type),
@@ -104,7 +104,7 @@ QueryTerm & QueryTerm::operator = (const QueryTerm &) = default;
QueryTerm::QueryTerm(QueryTerm &&) = default;
QueryTerm & QueryTerm::operator = (QueryTerm &&) = default;
-QueryTerm::~QueryTerm() { }
+QueryTerm::~QueryTerm() = default;
void
QueryTermSimple::visitMembers(vespalib::ObjectVisitor & visitor) const
@@ -301,9 +301,9 @@ void QueryTerm::resizeFieldId(size_t fieldNo)
}
}
-void QueryTerm::add(unsigned pos, unsigned context, int32_t weight_)
+void QueryTerm::add(unsigned pos, unsigned context, uint32_t elemId, int32_t weight_)
{
- _hitList.emplace_back(pos, context, weight_);
+ _hitList.emplace_back(pos, context, elemId, weight_);
}
template <int B>
@@ -344,7 +344,7 @@ QueryTermSimple::QueryTermSimple() :
_diversityAttribute()
{ }
-QueryTermSimple::~QueryTermSimple() { }
+QueryTermSimple::~QueryTermSimple() = default;
namespace {
diff --git a/searchlib/src/vespa/searchlib/query/queryterm.h b/searchlib/src/vespa/searchlib/query/queryterm.h
index 423b8d28efb..457a2feeeed 100644
--- a/searchlib/src/vespa/searchlib/query/queryterm.h
+++ b/searchlib/src/vespa/searchlib/query/queryterm.h
@@ -173,7 +173,7 @@ public:
/// Gives you all phrases of this tree. Indicating that they are all const.
void getPhrases(ConstQueryNodeRefList & tl) const override;
- void add(unsigned pos, unsigned context, int32_t weight);
+ void add(unsigned pos, unsigned context, uint32_t elemId, int32_t weight);
EncodingBitMap encoding() const { return _encoding; }
size_t termLen() const { return getTermLen(); }
const string & index() const { return _index; }
diff --git a/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp b/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp
index 31f53fee300..78531f41cf8 100644
--- a/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp
+++ b/vsm/src/vespa/vsm/searcher/fieldsearcher.cpp
@@ -73,6 +73,7 @@ FieldSearcher::FieldSearcher(const FieldIdT & fId, bool defaultPrefix) :
_field(fId),
_matchType(defaultPrefix ? PREFIX : REGULAR),
_maxFieldLength(0x100000),
+ _currentElementId(0),
_currentElementWeight(1),
_pureUsAsciiCount(0),
_pureUsAsciiFieldCount(0),
@@ -85,9 +86,7 @@ FieldSearcher::FieldSearcher(const FieldIdT & fId, bool defaultPrefix) :
zeroStat();
}
-FieldSearcher::~FieldSearcher()
-{
-}
+FieldSearcher::~FieldSearcher() = default;
bool FieldSearcher::search(const StorageDocument & doc)
{
@@ -275,6 +274,7 @@ FieldSearcher::IteratorHandler::onPrimitive(uint32_t, const Content & c)
{
LOG(spam, "onPrimitive: field value '%s'", c.getValue().toString().c_str());
_searcher.setCurrentWeight(c.getWeight());
+ _searcher.setCurrentElementId(getArrayIndex());
_searcher.onValue(c.getValue());
}
diff --git a/vsm/src/vespa/vsm/searcher/fieldsearcher.h b/vsm/src/vespa/vsm/searcher/fieldsearcher.h
index 236382be5f9..2bf976de017 100644
--- a/vsm/src/vespa/vsm/searcher/fieldsearcher.h
+++ b/vsm/src/vespa/vsm/searcher/fieldsearcher.h
@@ -95,11 +95,13 @@ private:
void prepareFieldId();
void setCurrentWeight(int32_t weight) { _currentElementWeight = weight; }
+ void setCurrentElementId(int32_t weight) { _currentElementId = weight; }
bool onSearch(const StorageDocument & doc);
virtual void onValue(const document::FieldValue & fv) = 0;
FieldIdT _field;
MatchType _matchType;
unsigned _maxFieldLength;
+ uint32_t _currentElementId;
int32_t _currentElementWeight; // Contains the weight of the current item being evaluated.
/// Number of bytes in blocks containing pure us-ascii
unsigned _pureUsAsciiCount;
@@ -124,7 +126,7 @@ protected:
* For each call to onValue() a batch of words are processed, and the position is local to this batch.
**/
void addHit(search::QueryTerm & qt, uint32_t pos) const {
- qt.add(_words + pos, field(), getCurrentWeight());
+ qt.add(_words + pos, field(), _currentElementId, getCurrentWeight());
}
public:
static search::byte _foldLowCase[256];
diff --git a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
index 21fa1d9ed02..e6af5fb6477 100644
--- a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
+++ b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
@@ -216,7 +216,7 @@ DocsumFilter::DocsumFilter(const DocsumToolsPtr &tools, const IDocSumCache & doc
_emptyFieldPath()
{ }
-DocsumFilter::~DocsumFilter() { }
+DocsumFilter::~DocsumFilter() =default;
void DocsumFilter::init(const FieldMap & fieldMap, const FieldPathMapT & fieldPathMap)
{
diff --git a/vsm/src/vespa/vsm/vsm/docsumfilter.h b/vsm/src/vespa/vsm/vsm/docsumfilter.h
index a3f8a8539f1..2d1ab6984e4 100644
--- a/vsm/src/vespa/vsm/vsm/docsumfilter.h
+++ b/vsm/src/vespa/vsm/vsm/docsumfilter.h
@@ -54,7 +54,7 @@ private:
public:
DocsumFilter(const DocsumToolsPtr & tools, const IDocSumCache & docsumCache);
- virtual ~DocsumFilter();
+ ~DocsumFilter() override;
const DocsumToolsPtr & getTools() const { return _tools; }
/**
diff --git a/vsm/src/vespa/vsm/vsm/vsm-adapter.cpp b/vsm/src/vespa/vsm/vsm/vsm-adapter.cpp
index d5078102e5d..1cd35e7ca61 100644
--- a/vsm/src/vespa/vsm/vsm/vsm-adapter.cpp
+++ b/vsm/src/vespa/vsm/vsm/vsm-adapter.cpp
@@ -46,7 +46,7 @@ void GetDocsumsStateCallback::FillDocumentLocations(GetDocsumsState *state, IDoc
}
-GetDocsumsStateCallback::~GetDocsumsStateCallback() { }
+GetDocsumsStateCallback::~GetDocsumsStateCallback() = default;
DocsumTools::FieldSpec::FieldSpec() :
_outputName(),
@@ -54,7 +54,7 @@ DocsumTools::FieldSpec::FieldSpec() :
_command(VsmsummaryConfig::Fieldmap::NONE)
{ }
-DocsumTools::FieldSpec::~FieldSpec() {}
+DocsumTools::FieldSpec::~FieldSpec() = default;
DocsumTools::DocsumTools(std::unique_ptr<DynamicDocsumWriter> writer) :
_writer(std::move(writer)),
@@ -64,7 +64,7 @@ DocsumTools::DocsumTools(std::unique_ptr<DynamicDocsumWriter> writer) :
{ }
-DocsumTools::~DocsumTools() { }
+DocsumTools::~DocsumTools() = default;
bool
DocsumTools::obtainFieldNames(const FastS_VsmsummaryHandle &cfg)
@@ -174,8 +174,6 @@ VSMAdapter::VSMAdapter(const vespalib::string & highlightindexes, const vespalib
}
-VSMAdapter::~VSMAdapter()
-{
-}
+VSMAdapter::~VSMAdapter() = default;
-} // namespace vsm
+}