summaryrefslogtreecommitdiffstats
path: root/searchsummary
diff options
context:
space:
mode:
authorGeir Storli <geirst@verizonmedia.com>2020-06-05 07:39:01 +0000
committerGeir Storli <geirst@verizonmedia.com>2020-06-05 13:58:10 +0000
commit6e3e3f2ce4322be9d9c7bbafc71236f3cb834e5a (patch)
tree3cdfcf6f718bf21bc43ba9ccfbb2810c539df67d /searchsummary
parent4c7a62d81082a1e63613b3e3864ba4b9c17be292 (diff)
Support filtering of matched elements for multi-value attributes.
Diffstat (limited to 'searchsummary')
-rw-r--r--searchsummary/CMakeLists.txt1
-rw-r--r--searchsummary/src/tests/docsummary/attribute_combiner/CMakeLists.txt1
-rw-r--r--searchsummary/src/tests/docsummary/attribute_combiner/attribute_combiner_test.cpp169
-rw-r--r--searchsummary/src/tests/docsummary/attributedfw/CMakeLists.txt11
-rw-r--r--searchsummary/src/tests/docsummary/attributedfw/attributedfw_test.cpp150
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp52
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/attributedfw.h8
-rw-r--r--searchsummary/src/vespa/searchsummary/test/CMakeLists.txt1
-rw-r--r--searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.cpp72
-rw-r--r--searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.h37
-rw-r--r--searchsummary/src/vespa/searchsummary/test/mock_state_callback.h35
11 files changed, 386 insertions, 151 deletions
diff --git a/searchsummary/CMakeLists.txt b/searchsummary/CMakeLists.txt
index 787925521ef..3792f2b6218 100644
--- a/searchsummary/CMakeLists.txt
+++ b/searchsummary/CMakeLists.txt
@@ -26,6 +26,7 @@ vespa_define_module(
src/tests/docsumformat
src/tests/docsummary
src/tests/docsummary/attribute_combiner
+ src/tests/docsummary/attributedfw
src/tests/docsummary/matched_elements_filter
src/tests/docsummary/slime_summary
src/tests/extractkeywords
diff --git a/searchsummary/src/tests/docsummary/attribute_combiner/CMakeLists.txt b/searchsummary/src/tests/docsummary/attribute_combiner/CMakeLists.txt
index cffdef25e5b..3ac95211aec 100644
--- a/searchsummary/src/tests/docsummary/attribute_combiner/CMakeLists.txt
+++ b/searchsummary/src/tests/docsummary/attribute_combiner/CMakeLists.txt
@@ -5,6 +5,7 @@ vespa_add_executable(searchsummary_attribute_combiner_test_app TEST
attribute_combiner_test.cpp
DEPENDS
searchsummary
+ searchsummary_test
GTest::GTest
)
vespa_add_test(NAME searchsummary_attribute_combiner_test_app COMMAND searchsummary_attribute_combiner_test_app)
diff --git a/searchsummary/src/tests/docsummary/attribute_combiner/attribute_combiner_test.cpp b/searchsummary/src/tests/docsummary/attribute_combiner/attribute_combiner_test.cpp
index c64c5b2ed7d..eaeaa27f053 100644
--- a/searchsummary/src/tests/docsummary/attribute_combiner/attribute_combiner_test.cpp
+++ b/searchsummary/src/tests/docsummary/attribute_combiner/attribute_combiner_test.cpp
@@ -1,19 +1,16 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/searchcommon/common/undefinedvalues.h>
-#include <vespa/searchlib/attribute/attributefactory.h>
-#include <vespa/searchlib/attribute/attributemanager.h>
#include <vespa/searchlib/attribute/attributevector.h>
-#include <vespa/searchlib/attribute/attributevector.hpp>
-#include <vespa/searchlib/attribute/floatbase.h>
-#include <vespa/searchlib/attribute/integerbase.h>
-#include <vespa/searchlib/attribute/stringbase.h>
#include <vespa/searchlib/common/matching_elements.h>
#include <vespa/searchlib/common/matching_elements_fields.h>
#include <vespa/searchlib/util/slime_output_raw_buf_adapter.h>
+#include <vespa/searchsummary/docsummary/docsumfieldwriter.h>
#include <vespa/searchsummary/docsummary/docsumstate.h>
#include <vespa/searchsummary/docsummary/docsum_field_writer_state.h>
#include <vespa/searchsummary/docsummary/attribute_combiner_dfw.h>
+#include <vespa/searchsummary/test/mock_attribute_manager.h>
+#include <vespa/searchsummary/test/mock_state_callback.h>
#include <vespa/searchsummary/test/slime_value.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/vespalib/gtest/gtest.h>
@@ -21,150 +18,24 @@
#include <vespa/log/log.h>
LOG_SETUP("attribute_combiner_test");
-using search::AttributeFactory;
-using search::AttributeManager;
-using search::AttributeVector;
-using search::FloatingPointAttribute;
-using search::IntegerAttribute;
-using search::MatchingElements;
-using search::StringAttribute;
using search::attribute::BasicType;
-using search::attribute::CollectionType;
-using search::attribute::Config;
-using search::attribute::IAttributeVector;
using search::attribute::getUndefined;
using search::docsummary::AttributeCombinerDFW;
using search::docsummary::GetDocsumsState;
using search::docsummary::GetDocsumsStateCallback;
using search::docsummary::IDocsumEnvironment;
using search::docsummary::IDocsumFieldWriter;
+using search::docsummary::test::MockAttributeManager;
+using search::docsummary::test::MockStateCallback;
using search::docsummary::test::SlimeValue;
namespace {
-struct AttributeManagerFixture
-{
- AttributeManager mgr;
-
- AttributeManagerFixture();
-
- ~AttributeManagerFixture();
-
- template <typename AttributeType, typename ValueType>
- void
- buildAttribute(const vespalib::string &name,
- BasicType type,
- std::vector<std::vector<ValueType>> values);
-
- void
- buildStringAttribute(const vespalib::string &name,
- std::vector<std::vector<vespalib::string>> values);
- void
- buildFloatAttribute(const vespalib::string &name,
- std::vector<std::vector<double>> values);
-
- void
- buildIntegerAttribute(const vespalib::string &name,
- BasicType type,
- std::vector<std::vector<IAttributeVector::largeint_t>> values);
-};
-
-AttributeManagerFixture::AttributeManagerFixture()
- : mgr()
-{
- buildStringAttribute("array.name", {{"n1.1", "n1.2"}, {"n2"}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
- buildIntegerAttribute("array.val", BasicType::Type::INT8, {{ 10, 11}, {20, 21 }, {30}, { getUndefined<int8_t>(), 41}, {}});
- buildFloatAttribute("array.fval", {{ 110.0}, { 120.0, 121.0 }, { 130.0, 131.0}, { getUndefined<double>(), 141.0 }, {}});
- buildStringAttribute("smap.key", {{"k1.1", "k1.2"}, {"k2"}, {"k3.1", "k3.2"}, {"", "k4.2"}, {}});
- buildStringAttribute("smap.value.name", {{"n1.1", "n1.2"}, {"n2"}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
- buildIntegerAttribute("smap.value.val", BasicType::Type::INT8, {{ 10, 11}, {20, 21 }, {30}, { getUndefined<int8_t>(), 41}, {}});
- buildFloatAttribute("smap.value.fval", {{ 110.0}, { 120.0, 121.0 }, { 130.0, 131.0}, { getUndefined<double>(), 141.0 }, {}});
- buildStringAttribute("map.key", {{"k1.1", "k1.2"}, {"k2"}, {"k3.1"}, {"", "k4.2"}, {}});
- buildStringAttribute("map.value", {{"n1.1", "n1.2"}, {}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
-}
-
-AttributeManagerFixture::~AttributeManagerFixture() = default;
-
-template <typename AttributeType, typename ValueType>
-void
-AttributeManagerFixture::buildAttribute(const vespalib::string &name,
- BasicType type,
- std::vector<std::vector<ValueType>> values)
-{
- Config cfg(type, CollectionType::Type::ARRAY);
- auto attrBase = AttributeFactory::createAttribute(name, cfg);
- EXPECT_TRUE(attrBase);
- auto attr = std::dynamic_pointer_cast<AttributeType>(attrBase);
- EXPECT_TRUE(attr);
- attr->addReservedDoc();
- for (const auto &docValues : values) {
- uint32_t docId = 0;
- EXPECT_TRUE(attr->addDoc(docId));
- EXPECT_NE(0u, docId);
- for (const auto &value : docValues) {
- attr->append(docId, value, 1);
- }
- attr->commit();
- }
- EXPECT_TRUE(mgr.add(attr));
-}
-
-void
-AttributeManagerFixture::buildStringAttribute(const vespalib::string &name,
- std::vector<std::vector<vespalib::string>> values)
-{
- buildAttribute<StringAttribute, vespalib::string>(name, BasicType::Type::STRING, std::move(values));
-}
-
-void
-AttributeManagerFixture::buildFloatAttribute(const vespalib::string &name,
- std::vector<std::vector<double>> values)
-{
- buildAttribute<FloatingPointAttribute, double>(name, BasicType::Type::DOUBLE, std::move(values));
-}
-
-void
-AttributeManagerFixture::buildIntegerAttribute(const vespalib::string &name,
- BasicType type,
- std::vector<std::vector<IAttributeVector::largeint_t>> values)
-{
- buildAttribute<IntegerAttribute, IAttributeVector::largeint_t>(name, type, std::move(values));
-}
-
-
-class DummyStateCallback : public GetDocsumsStateCallback
-{
-public:
- MatchingElements _matching_elements;
-
- DummyStateCallback();
- void FillSummaryFeatures(GetDocsumsState *, IDocsumEnvironment *) override { }
- void FillRankFeatures(GetDocsumsState *, IDocsumEnvironment *) override { }
- void ParseLocation(GetDocsumsState *) override { }
- std::unique_ptr<MatchingElements> fill_matching_elements(const search::MatchingElementsFields &) override { return std::make_unique<MatchingElements>(_matching_elements); }
- ~DummyStateCallback() override { }
-};
-
-DummyStateCallback::DummyStateCallback()
- : GetDocsumsStateCallback(),
- _matching_elements()
-{
- _matching_elements.add_matching_elements(1, "array", {1});
- _matching_elements.add_matching_elements(3, "array", {0});
- _matching_elements.add_matching_elements(4, "array", {1});
- _matching_elements.add_matching_elements(1, "smap", {1});
- _matching_elements.add_matching_elements(3, "smap", {0});
- _matching_elements.add_matching_elements(4, "smap", {1});
- _matching_elements.add_matching_elements(1, "map", {1});
- _matching_elements.add_matching_elements(3, "map", {0});
- _matching_elements.add_matching_elements(4, "map", {1});
-}
-
struct AttributeCombinerTest : public ::testing::Test
{
- AttributeManagerFixture attrs;
+ MockAttributeManager attrs;
std::unique_ptr<IDocsumFieldWriter> writer;
- DummyStateCallback stateCallback;
+ MockStateCallback callback;
GetDocsumsState state;
std::shared_ptr<search::MatchingElementsFields> _matching_elems_fields;
@@ -177,11 +48,31 @@ struct AttributeCombinerTest : public ::testing::Test
AttributeCombinerTest::AttributeCombinerTest()
: attrs(),
writer(),
- stateCallback(),
- state(stateCallback),
+ callback(),
+ state(callback),
_matching_elems_fields()
{
- state._attrCtx = attrs.mgr.createContext();
+ attrs.build_string_attribute("array.name", {{"n1.1", "n1.2"}, {"n2"}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
+ attrs.build_int_attribute("array.val", BasicType::Type::INT8, {{ 10, 11}, {20, 21 }, {30}, { getUndefined<int8_t>(), 41}, {}});
+ attrs.build_float_attribute("array.fval", {{ 110.0}, { 120.0, 121.0 }, { 130.0, 131.0}, { getUndefined<double>(), 141.0 }, {}});
+ attrs.build_string_attribute("smap.key", {{"k1.1", "k1.2"}, {"k2"}, {"k3.1", "k3.2"}, {"", "k4.2"}, {}});
+ attrs.build_string_attribute("smap.value.name", {{"n1.1", "n1.2"}, {"n2"}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
+ attrs.build_int_attribute("smap.value.val", BasicType::Type::INT8, {{ 10, 11}, {20, 21 }, {30}, { getUndefined<int8_t>(), 41}, {}});
+ attrs.build_float_attribute("smap.value.fval", {{ 110.0}, { 120.0, 121.0 }, { 130.0, 131.0}, { getUndefined<double>(), 141.0 }, {}});
+ attrs.build_string_attribute("map.key", {{"k1.1", "k1.2"}, {"k2"}, {"k3.1"}, {"", "k4.2"}, {}});
+ attrs.build_string_attribute("map.value", {{"n1.1", "n1.2"}, {}, {"n3.1", "n3.2"}, {"", "n4.2"}, {}});
+
+ callback.add_matching_elements(1, "array", {1});
+ callback.add_matching_elements(3, "array", {0});
+ callback.add_matching_elements(4, "array", {1});
+ callback.add_matching_elements(1, "smap", {1});
+ callback.add_matching_elements(3, "smap", {0});
+ callback.add_matching_elements(4, "smap", {1});
+ callback.add_matching_elements(1, "map", {1});
+ callback.add_matching_elements(3, "map", {0});
+ callback.add_matching_elements(4, "map", {1});
+
+ state._attrCtx = attrs.mgr().createContext();
}
AttributeCombinerTest::~AttributeCombinerTest() = default;
diff --git a/searchsummary/src/tests/docsummary/attributedfw/CMakeLists.txt b/searchsummary/src/tests/docsummary/attributedfw/CMakeLists.txt
new file mode 100644
index 00000000000..8bdf30273f2
--- /dev/null
+++ b/searchsummary/src/tests/docsummary/attributedfw/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+find_package(GTest REQUIRED)
+vespa_add_executable(searchsummary_attributedfw_test_app TEST
+ SOURCES
+ attributedfw_test.cpp
+ DEPENDS
+ searchsummary
+ searchsummary_test
+ GTest::GTest
+)
+vespa_add_test(NAME searchsummary_attributedfw_test_app COMMAND searchsummary_attributedfw_test_app)
diff --git a/searchsummary/src/tests/docsummary/attributedfw/attributedfw_test.cpp b/searchsummary/src/tests/docsummary/attributedfw/attributedfw_test.cpp
new file mode 100644
index 00000000000..7bea92ec8f3
--- /dev/null
+++ b/searchsummary/src/tests/docsummary/attributedfw/attributedfw_test.cpp
@@ -0,0 +1,150 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/searchlib/common/matching_elements_fields.h>
+#include <vespa/searchsummary/docsummary/attributedfw.h>
+#include <vespa/searchsummary/test/mock_attribute_manager.h>
+#include <vespa/searchsummary/test/mock_state_callback.h>
+#include <vespa/searchsummary/test/slime_value.h>
+#include <vespa/vespalib/gtest/gtest.h>
+
+#include <vespa/log/log.h>
+LOG_SETUP("attributedfw_test");
+
+using search::MatchingElements;
+using search::MatchingElementsFields;
+using search::attribute::BasicType;
+using search::attribute::CollectionType;
+using search::docsummary::AttributeDFWFactory;
+using search::docsummary::GetDocsumsState;
+using search::docsummary::IDocsumFieldWriter;
+using search::docsummary::test::MockAttributeManager;
+using search::docsummary::test::MockStateCallback;
+using search::docsummary::test::SlimeValue;
+
+using ElementVector = std::vector<uint32_t>;
+
+class AttributeDFWTest : public ::testing::Test {
+protected:
+ MockAttributeManager _attrs;
+ std::unique_ptr<IDocsumFieldWriter> _writer;
+ MockStateCallback _callback;
+ GetDocsumsState _state;
+ std::shared_ptr<search::MatchingElementsFields> _matching_elems_fields;
+ vespalib::string _field_name;
+
+public:
+ AttributeDFWTest()
+ : _attrs(),
+ _writer(),
+ _callback(),
+ _state(_callback),
+ _matching_elems_fields(),
+ _field_name()
+ {
+ _attrs.build_string_attribute("array_str", { {"a", "b", "c"}, {} });
+ _attrs.build_int_attribute("array_int", BasicType::INT32, { {10, 20, 30}, {} });
+ _attrs.build_float_attribute("array_float", { {10.5, 20.5, 30.5}, {} });
+
+ _attrs.build_string_attribute("wset_str", { {"a", "b", "c"}, {} }, CollectionType::WSET);
+ _attrs.build_int_attribute("wset_int", BasicType::INT32, { {10, 20, 30}, {} }, CollectionType::WSET);
+ _attrs.build_float_attribute("wset_float", { {10.5, 20.5, 30.5}, {} }, CollectionType::WSET);
+
+ _state._attrCtx = _attrs.mgr().createContext();
+ }
+ ~AttributeDFWTest() {}
+
+ void setup(const vespalib::string& field_name, bool filter_elements) {
+ if (filter_elements) {
+ _matching_elems_fields = std::make_shared<MatchingElementsFields>();
+ }
+ _writer = AttributeDFWFactory::create(_attrs.mgr(), field_name, filter_elements, _matching_elems_fields);
+ _writer->setIndex(0);
+ _field_name = field_name;
+ _state._attributes.resize(1);
+ _state._attributes[0] = _state._attrCtx->getAttribute(field_name);
+ }
+
+ void expect_field(const vespalib::string& exp_slime_as_json, uint32_t docid) {
+ vespalib::Slime act;
+ vespalib::slime::SlimeInserter inserter(act);
+ _writer->insertField(docid, nullptr, &_state, search::docsummary::RES_JSONSTRING, inserter);
+
+ SlimeValue exp(exp_slime_as_json);
+ EXPECT_EQ(exp.slime, act);
+ }
+
+ void expect_filtered(const ElementVector& matching_elems, const std::string& exp_slime_as_json, uint32_t docid = 1) {
+ _callback.clear();
+ _callback.add_matching_elements(docid, _field_name, matching_elems);
+ _state._matching_elements = std::unique_ptr<MatchingElements>();
+ expect_field(exp_slime_as_json, docid);
+ }
+};
+
+TEST_F(AttributeDFWTest, outputs_slime_for_array_of_string)
+{
+ setup("array_str", false);
+ expect_field("[ 'a', 'b', 'c' ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, outputs_slime_for_array_of_int)
+{
+ setup("array_int", false);
+ expect_field("[ 10, 20, 30 ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, outputs_slime_for_array_of_float)
+{
+ setup("array_float", false);
+ expect_field("[ 10.5, 20.5, 30.5 ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, outputs_slime_for_wset_of_string)
+{
+ setup("wset_str", false);
+ expect_field("[ {'item':'a', 'weight':1}, {'item':'b', 'weight':1}, {'item':'c', 'weight':1} ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, outputs_slime_for_wset_of_int)
+{
+ setup("wset_int", false);
+ expect_field("[ {'item':10, 'weight':1}, {'item':20, 'weight':1}, {'item':30, 'weight':1} ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, outputs_slime_for_wset_of_float)
+{
+ setup("wset_float", false);
+ expect_field("[ {'item':10.5, 'weight':1}, {'item':20.5, 'weight':1}, {'item':30.5, 'weight':1} ]", 1);
+ expect_field("null", 2);
+}
+
+TEST_F(AttributeDFWTest, matched_elements_fields_is_populated)
+{
+ setup("array_str", true);
+ EXPECT_TRUE(_matching_elems_fields->has_field("array_str"));
+}
+
+TEST_F(AttributeDFWTest, filteres_matched_elements_in_array_attribute)
+{
+ setup("array_str", true);
+ expect_filtered({}, "[]");
+ expect_filtered({0}, "[ 'a' ]");
+ expect_filtered({1, 2}, "[ 'b', 'c' ]");
+ expect_filtered({3}, "[]");
+}
+
+TEST_F(AttributeDFWTest, filteres_matched_elements_in_wset_attribute)
+{
+ setup("wset_str", true);
+ expect_filtered({}, "[]");
+ expect_filtered({0}, "[ {'item':'a', 'weight':1} ]");
+ expect_filtered({1, 2}, "[ {'item':'b', 'weight':1}, {'item':'c', 'weight':1} ]");
+ expect_filtered({3}, "[]");
+}
+
+GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
index 704876f4838..05ba12ddff9 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
+++ b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.cpp
@@ -9,6 +9,8 @@
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/searchlib/attribute/integerbase.h>
#include <vespa/searchlib/attribute/stringbase.h>
+#include <vespa/searchlib/common/matching_elements.h>
+#include <vespa/searchlib/common/matching_elements_fields.h>
#include <vespa/searchlib/tensor/i_tensor_attribute.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/vespalib/objects/nbostream.h>
@@ -139,12 +141,21 @@ template <typename DataType>
class MultiAttrDFW : public AttrDFW {
private:
bool _is_weighted_set;
+ bool _filter_elements;
+ std::shared_ptr<MatchingElementsFields> _matching_elems_fields;
public:
- explicit MultiAttrDFW(const vespalib::string& attr_name, bool is_weighted_set)
+ explicit MultiAttrDFW(const vespalib::string& attr_name, bool is_weighted_set,
+ bool filter_elements, std::shared_ptr<MatchingElementsFields> matching_elems_fields)
: AttrDFW(attr_name),
- _is_weighted_set(is_weighted_set)
- {}
+ _is_weighted_set(is_weighted_set),
+ _filter_elements(filter_elements),
+ _matching_elems_fields(std::move(matching_elems_fields))
+ {
+ if (filter_elements && _matching_elems_fields) {
+ _matching_elems_fields->add_field(attr_name);
+ }
+ }
void insertField(uint32_t docid, GetDocsumsState* state, ResType type, Inserter& target) override;
};
@@ -202,8 +213,19 @@ MultiAttrDFW<DataType>::insertField(uint32_t docid, GetDocsumsState* state, ResT
Cursor &arr = target.insertArray();
std::vector<DataType> elements(entries);
entries = std::min(entries, attr.get(docid, elements.data(), entries));
- for (uint32_t i = 0; i < entries; ++i) {
- insert_element(elements, i, _is_weighted_set, arr);
+
+ if (_filter_elements) {
+ const auto& matching_elems = state->get_matching_elements(*_matching_elems_fields)
+ .get_matching_elements(docid, getAttributeName());
+ if (!matching_elems.empty() && matching_elems.back() < entries) {
+ for (uint32_t id_to_keep : matching_elems) {
+ insert_element(elements, id_to_keep, _is_weighted_set, arr);
+ }
+ }
+ } else {
+ for (uint32_t i = 0; i < entries; ++i) {
+ insert_element(elements, i, _is_weighted_set, arr);
+ }
}
}
@@ -212,14 +234,17 @@ MultiAttrDFW<DataType>::insertField(uint32_t docid, GetDocsumsState* state, ResT
namespace {
std::unique_ptr<IDocsumFieldWriter>
-create_multi_writer(const IAttributeVector& attr)
+create_multi_writer(const IAttributeVector& attr,
+ bool filter_elements,
+ std::shared_ptr<MatchingElementsFields> matching_elems_fields)
{
auto type = attr.getBasicType();
bool is_weighted_set = attr.hasWeightedSetType();
switch (type) {
case BasicType::NONE:
case BasicType::STRING: {
- return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedString>>(attr.getName(), is_weighted_set);
+ return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedString>>(attr.getName(), is_weighted_set,
+ filter_elements, std::move(matching_elems_fields));
}
case BasicType::BOOL:
case BasicType::UINT2:
@@ -228,11 +253,13 @@ create_multi_writer(const IAttributeVector& attr)
case BasicType::INT16:
case BasicType::INT32:
case BasicType::INT64: {
- return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedInt>>(attr.getName(), is_weighted_set);
+ return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedInt>>(attr.getName(), is_weighted_set,
+ filter_elements, std::move(matching_elems_fields));
}
case BasicType::FLOAT:
case BasicType::DOUBLE: {
- return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedFloat>>(attr.getName(), is_weighted_set);
+ return std::make_unique<MultiAttrDFW<IAttributeVector::WeightedFloat>>(attr.getName(), is_weighted_set,
+ filter_elements, std::move(matching_elems_fields));
}
default:
// should not happen
@@ -244,7 +271,10 @@ create_multi_writer(const IAttributeVector& attr)
}
std::unique_ptr<IDocsumFieldWriter>
-AttributeDFWFactory::create(IAttributeManager& attr_mgr, const vespalib::string& attr_name)
+AttributeDFWFactory::create(IAttributeManager& attr_mgr,
+ const vespalib::string& attr_name,
+ bool filter_elements,
+ std::shared_ptr<MatchingElementsFields> matching_elems_fields)
{
auto ctx = attr_mgr.createContext();
const auto* attr = ctx->getAttribute(attr_name);
@@ -253,7 +283,7 @@ AttributeDFWFactory::create(IAttributeManager& attr_mgr, const vespalib::string&
return std::unique_ptr<IDocsumFieldWriter>();
}
if (attr->hasMultiValue()) {
- return create_multi_writer(*attr);
+ return create_multi_writer(*attr, filter_elements, std::move(matching_elems_fields));
} else {
return std::make_unique<SingleAttrDFW>(attr->getName());
}
diff --git a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.h b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.h
index 03de2cc76b4..55a30f0bb7b 100644
--- a/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.h
+++ b/searchsummary/src/vespa/searchsummary/docsummary/attributedfw.h
@@ -4,6 +4,8 @@
#include "docsumfieldwriter.h"
+
+namespace search { class MatchingElementsFields; }
namespace search::attribute { class IAttributeVector; }
namespace search::docsummary {
@@ -13,7 +15,11 @@ namespace search::docsummary {
*/
class AttributeDFWFactory {
public:
- static std::unique_ptr<IDocsumFieldWriter> create(IAttributeManager& attr_mgr, const vespalib::string& attr_name);
+ static std::unique_ptr<IDocsumFieldWriter> create(IAttributeManager& attr_mgr,
+ const vespalib::string& attr_name,
+ bool filter_elements = false,
+ std::shared_ptr<MatchingElementsFields> matching_elems_fields
+ = std::shared_ptr<MatchingElementsFields>());
};
class AttrDFW : public ISimpleDFW
diff --git a/searchsummary/src/vespa/searchsummary/test/CMakeLists.txt b/searchsummary/src/vespa/searchsummary/test/CMakeLists.txt
index aea75ffb244..ae4414bb078 100644
--- a/searchsummary/src/vespa/searchsummary/test/CMakeLists.txt
+++ b/searchsummary/src/vespa/searchsummary/test/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(searchsummary_test OBJECT
SOURCES
+ mock_attribute_manager.cpp
AFTER
searchsummary_config
)
diff --git a/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.cpp b/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.cpp
new file mode 100644
index 00000000000..bd7307d1624
--- /dev/null
+++ b/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.cpp
@@ -0,0 +1,72 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "mock_attribute_manager.h"
+#include <vespa/searchlib/attribute/attributefactory.h>
+#include <vespa/searchlib/attribute/attributevector.h>
+#include <vespa/searchlib/attribute/attributevector.hpp>
+#include <vespa/searchlib/attribute/floatbase.h>
+#include <vespa/searchlib/attribute/integerbase.h>
+#include <vespa/searchlib/attribute/stringbase.h>
+#include <cassert>
+
+using search::attribute::BasicType;
+using search::attribute::CollectionType;
+using search::attribute::Config;
+
+namespace search::docsummary::test {
+
+template <typename AttributeType, typename ValueType>
+void
+MockAttributeManager::build_attribute(const vespalib::string& name, BasicType type,
+ search::attribute::CollectionType col_type,
+ const std::vector<std::vector<ValueType>>& values)
+{
+ Config cfg(type, col_type);
+ auto attr_base = AttributeFactory::createAttribute(name, cfg);
+ assert(attr_base);
+ auto attr = std::dynamic_pointer_cast<AttributeType>(attr_base);
+ assert(attr);
+ attr->addReservedDoc();
+ for (const auto& docValues : values) {
+ uint32_t docId = 0;
+ attr->addDoc(docId);
+ for (const auto& value : docValues) {
+ attr->append(docId, value, 1);
+ }
+ attr->commit();
+ }
+ _mgr.add(attr);
+}
+
+MockAttributeManager::MockAttributeManager()
+ : _mgr()
+{
+}
+
+MockAttributeManager::~MockAttributeManager() = default;
+
+void
+MockAttributeManager::build_string_attribute(const vespalib::string& name,
+ const std::vector<std::vector<vespalib::string>>& values,
+ CollectionType col_type)
+{
+ build_attribute<StringAttribute, vespalib::string>(name, BasicType::Type::STRING, col_type, values);
+}
+
+void
+MockAttributeManager::build_float_attribute(const vespalib::string& name,
+ const std::vector<std::vector<double>>& values,
+ CollectionType col_type)
+{
+ build_attribute<FloatingPointAttribute, double>(name, BasicType::Type::DOUBLE, col_type, values);
+}
+
+void
+MockAttributeManager::build_int_attribute(const vespalib::string& name, BasicType type,
+ const std::vector<std::vector<int64_t>>& values,
+ CollectionType col_type)
+{
+ build_attribute<IntegerAttribute, int64_t>(name, type, col_type, values);
+}
+
+}
diff --git a/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.h b/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.h
new file mode 100644
index 00000000000..a7e425e50b6
--- /dev/null
+++ b/searchsummary/src/vespa/searchsummary/test/mock_attribute_manager.h
@@ -0,0 +1,37 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/searchcommon/attribute/basictype.h>
+#include <vespa/searchlib/attribute/attributemanager.h>
+
+namespace search::docsummary::test {
+
+/**
+ * Class used to build attributes and populate a manager for testing.
+ */
+class MockAttributeManager {
+private:
+ AttributeManager _mgr;
+
+ template <typename AttributeType, typename ValueType>
+ void build_attribute(const vespalib::string& name, search::attribute::BasicType type,
+ search::attribute::CollectionType col_type,
+ const std::vector<std::vector<ValueType>>& values);
+
+public:
+ MockAttributeManager();
+ ~MockAttributeManager();
+ AttributeManager& mgr() { return _mgr; }
+
+ void build_string_attribute(const vespalib::string& name,
+ const std::vector<std::vector<vespalib::string>>& values,
+ search::attribute::CollectionType col_type = search::attribute::CollectionType::ARRAY);
+ void build_float_attribute(const vespalib::string& name,
+ const std::vector<std::vector<double>>& values,
+ search::attribute::CollectionType col_type = search::attribute::CollectionType::ARRAY);
+ void build_int_attribute(const vespalib::string& name, search::attribute::BasicType type,
+ const std::vector<std::vector<int64_t>>& values,
+ search::attribute::CollectionType col_type = search::attribute::CollectionType::ARRAY);
+
+};
+
+}
diff --git a/searchsummary/src/vespa/searchsummary/test/mock_state_callback.h b/searchsummary/src/vespa/searchsummary/test/mock_state_callback.h
new file mode 100644
index 00000000000..b3ee405c856
--- /dev/null
+++ b/searchsummary/src/vespa/searchsummary/test/mock_state_callback.h
@@ -0,0 +1,35 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/searchlib/common/matching_elements.h>
+#include <vespa/searchsummary/docsummary/docsumstate.h>
+
+namespace search::docsummary::test {
+
+class MockStateCallback : public GetDocsumsStateCallback {
+private:
+ MatchingElements _matching_elems;
+
+public:
+ MockStateCallback()
+ : GetDocsumsStateCallback(),
+ _matching_elems()
+ {
+ }
+ ~MockStateCallback() override { }
+ void FillSummaryFeatures(GetDocsumsState*, IDocsumEnvironment*) override { }
+ void FillRankFeatures(GetDocsumsState*, IDocsumEnvironment*) override { }
+ void ParseLocation(GetDocsumsState*) override { }
+ std::unique_ptr<MatchingElements> fill_matching_elements(const search::MatchingElementsFields&) override {
+ return std::make_unique<MatchingElements>(_matching_elems);
+ }
+
+ void add_matching_elements(uint32_t docid, const vespalib::string& field_name,
+ const std::vector<uint32_t>& elements) {
+ _matching_elems.add_matching_elements(docid, field_name, elements);
+ }
+ void clear() {
+ _matching_elems = MatchingElements();
+ }
+};
+
+}