diff options
author | Tor Egge <Tor.Egge@broadpark.no> | 2020-05-20 17:46:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-20 17:46:44 +0200 |
commit | 9cce00e2d7624b9b97e4f0f4d88cc76a20f0bd06 (patch) | |
tree | c58bcd4ec455e39ce26c2c354277d2cc78d7267c /searchlib | |
parent | b177a56fce6f2f6caf4389c2646f861ad2363838 (diff) | |
parent | 47e95a1a3506525c832517a4f8b0e925c9f12c02 (diff) |
Merge pull request #13331 from vespa-engine/geirst/prepare-for-matched-elements-only-on-primitive-types
Prepare to support matched-elements-only for arrays and weighted sets…
Diffstat (limited to 'searchlib')
14 files changed, 140 insertions, 134 deletions
diff --git a/searchlib/CMakeLists.txt b/searchlib/CMakeLists.txt index 47b382af3f1..e9e2087e9d1 100644 --- a/searchlib/CMakeLists.txt +++ b/searchlib/CMakeLists.txt @@ -104,8 +104,8 @@ vespa_define_module( src/tests/common/bitvector src/tests/common/location src/tests/common/matching_elements + src/tests/common/matching_elements_fields src/tests/common/resultset - src/tests/common/struct_field_mapper src/tests/common/summaryfeatures src/tests/diskindex/bitvector src/tests/diskindex/diskindex diff --git a/searchlib/src/tests/common/matching_elements_fields/CMakeLists.txt b/searchlib/src/tests/common/matching_elements_fields/CMakeLists.txt new file mode 100644 index 00000000000..3d6f338315a --- /dev/null +++ b/searchlib/src/tests/common/matching_elements_fields/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchlib_common_matching_elements_fields_test_app TEST + SOURCES + matching_elements_fields_test.cpp + DEPENDS + searchlib + gtest +) +vespa_add_test(NAME searchlib_common_matching_elements_fields_test_app COMMAND searchlib_common_matching_elements_fields_test_app) diff --git a/searchlib/src/tests/common/matching_elements_fields/matching_elements_fields_test.cpp b/searchlib/src/tests/common/matching_elements_fields/matching_elements_fields_test.cpp new file mode 100644 index 00000000000..766be30f8f1 --- /dev/null +++ b/searchlib/src/tests/common/matching_elements_fields/matching_elements_fields_test.cpp @@ -0,0 +1,55 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/vespalib/gtest/gtest.h> +#include <vespa/searchlib/common/matching_elements_fields.h> + +using namespace search; + +namespace { + +std::string str(const vespalib::string &s) { return std::string(s.data(), s.size()); } + +} + +struct MatchingElementsFieldsTest : ::testing::Test { + MatchingElementsFields fields; + MatchingElementsFieldsTest() : fields() { + fields.add_mapping("foo", "foo.a"); + fields.add_mapping("foo", "foo.b"); + fields.add_mapping("bar", "bar.x"); + fields.add_mapping("bar", "bar.y"); + fields.add_field("baz"); + } + ~MatchingElementsFieldsTest() = default; +}; + +TEST_F(MatchingElementsFieldsTest, require_that_field_can_be_identified) { + EXPECT_TRUE(fields.has_field("foo")); + EXPECT_TRUE(fields.has_field("bar")); + EXPECT_TRUE(fields.has_field("baz")); + EXPECT_TRUE(!fields.has_field("foo.a")); + EXPECT_TRUE(!fields.has_field("bar.x")); + EXPECT_TRUE(!fields.has_field("bogus")); +} + +TEST_F(MatchingElementsFieldsTest, require_that_struct_field_can_be_identified) { + EXPECT_TRUE(!fields.has_struct_field("foo")); + EXPECT_TRUE(!fields.has_struct_field("bar")); + EXPECT_TRUE(!fields.has_struct_field("baz")); + EXPECT_TRUE(fields.has_struct_field("foo.a")); + EXPECT_TRUE(fields.has_struct_field("bar.x")); + EXPECT_TRUE(!fields.has_struct_field("bogus")); +} + +TEST_F(MatchingElementsFieldsTest, require_that_struct_field_maps_to_enclosing_field_name) { + EXPECT_EQ(str(fields.get_enclosing_field("foo.a")), str("foo")); + EXPECT_EQ(str(fields.get_enclosing_field("foo.b")), str("foo")); + EXPECT_EQ(str(fields.get_enclosing_field("bar.x")), str("bar")); + EXPECT_EQ(str(fields.get_enclosing_field("bar.y")), str("bar")); +} + +TEST_F(MatchingElementsFieldsTest, require_that_nonexisting_struct_field_maps_to_empty_string) { + EXPECT_EQ(str(fields.get_enclosing_field("bogus")), str("")); +} + +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/common/struct_field_mapper/CMakeLists.txt b/searchlib/src/tests/common/struct_field_mapper/CMakeLists.txt deleted file mode 100644 index f5712d22989..00000000000 --- a/searchlib/src/tests/common/struct_field_mapper/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(searchlib_common_struct_field_mapper_test_app TEST - SOURCES - struct_field_mapper_test.cpp - DEPENDS - searchlib - gtest -) -vespa_add_test(NAME searchlib_common_struct_field_mapper_test_app COMMAND searchlib_common_struct_field_mapper_test_app) diff --git a/searchlib/src/tests/common/struct_field_mapper/struct_field_mapper_test.cpp b/searchlib/src/tests/common/struct_field_mapper/struct_field_mapper_test.cpp deleted file mode 100644 index c5368111859..00000000000 --- a/searchlib/src/tests/common/struct_field_mapper/struct_field_mapper_test.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/gtest/gtest.h> -#include <vespa/searchlib/common/struct_field_mapper.h> - -using namespace search; - -namespace { - -std::string str(const vespalib::string &s) { return std::string(s.data(), s.size()); } - -} - -struct StructFieldMapperTest : ::testing::Test { - StructFieldMapper mapper; - StructFieldMapperTest() : mapper() { - mapper.add_mapping("foo", "foo.a"); - mapper.add_mapping("foo", "foo.b"); - mapper.add_mapping("bar", "bar.x"); - mapper.add_mapping("bar", "bar.y"); - } - ~StructFieldMapperTest() = default; -}; - -TEST_F(StructFieldMapperTest, require_that_struct_field_can_be_identified) { - EXPECT_TRUE(mapper.is_struct_field("foo")); - EXPECT_TRUE(mapper.is_struct_field("bar")); - EXPECT_TRUE(!mapper.is_struct_field("foo.a")); - EXPECT_TRUE(!mapper.is_struct_field("bar.x")); - EXPECT_TRUE(!mapper.is_struct_field("bogus")); -} - -TEST_F(StructFieldMapperTest, require_that_struct_subfield_can_be_identified) { - EXPECT_TRUE(!mapper.is_struct_subfield("foo")); - EXPECT_TRUE(!mapper.is_struct_subfield("bar")); - EXPECT_TRUE(mapper.is_struct_subfield("foo.a")); - EXPECT_TRUE(mapper.is_struct_subfield("bar.x")); - EXPECT_TRUE(!mapper.is_struct_subfield("bogus")); -} - -TEST_F(StructFieldMapperTest, require_that_struct_subfield_maps_to_enclosing_struct_field_name) { - EXPECT_EQ(str(mapper.get_struct_field("foo.a")), str("foo")); - EXPECT_EQ(str(mapper.get_struct_field("foo.b")), str("foo")); - EXPECT_EQ(str(mapper.get_struct_field("bar.x")), str("bar")); - EXPECT_EQ(str(mapper.get_struct_field("bar.y")), str("bar")); -} - -TEST_F(StructFieldMapperTest, require_that_nonexisting_struct_subfield_maps_to_empty_string) { - EXPECT_EQ(str(mapper.get_struct_field("bogus")), str("")); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/vespa/searchlib/common/CMakeLists.txt b/searchlib/src/vespa/searchlib/common/CMakeLists.txt index 36264a2035b..5d30260a169 100644 --- a/searchlib/src/vespa/searchlib/common/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/common/CMakeLists.txt @@ -18,6 +18,7 @@ vespa_add_library(searchlib_common OBJECT locationiterators.cpp mapnames.cpp matching_elements.cpp + matching_elements_fields.cpp packets.cpp partialbitvector.cpp resultset.cpp @@ -26,7 +27,6 @@ vespa_add_library(searchlib_common OBJECT sortdata.cpp sortresults.cpp sortspec.cpp - struct_field_mapper.cpp threaded_compactable_lid_space.cpp tunefileinfo.cpp DEPENDS diff --git a/searchlib/src/vespa/searchlib/common/matching_elements.cpp b/searchlib/src/vespa/searchlib/common/matching_elements.cpp index 1a4653e267b..87049f7d843 100644 --- a/searchlib/src/vespa/searchlib/common/matching_elements.cpp +++ b/searchlib/src/vespa/searchlib/common/matching_elements.cpp @@ -9,19 +9,19 @@ MatchingElements::MatchingElements() = default; MatchingElements::~MatchingElements() = default; void -MatchingElements::add_matching_elements(uint32_t docid, const vespalib::string &struct_field_name, const std::vector<uint32_t> &elements) +MatchingElements::add_matching_elements(uint32_t docid, const vespalib::string &field_name, const std::vector<uint32_t> &elements) { - auto &list = _map[key_t(docid, struct_field_name)]; + auto &list = _map[key_t(docid, field_name)]; std::vector<uint32_t> new_list; std::set_union(list.begin(), list.end(), elements.begin(), elements.end(), std::back_inserter(new_list)); list = std::move(new_list); } const std::vector<uint32_t> & -MatchingElements::get_matching_elements(uint32_t docid, const vespalib::string &struct_field_name) const +MatchingElements::get_matching_elements(uint32_t docid, const vespalib::string &field_name) const { static const std::vector<uint32_t> empty; - auto res = _map.find(key_t(docid, struct_field_name)); + auto res = _map.find(key_t(docid, field_name)); if (res == _map.end()) { return empty; } diff --git a/searchlib/src/vespa/searchlib/common/matching_elements.h b/searchlib/src/vespa/searchlib/common/matching_elements.h index b31b258ea4c..60fe7167bfd 100644 --- a/searchlib/src/vespa/searchlib/common/matching_elements.h +++ b/searchlib/src/vespa/searchlib/common/matching_elements.h @@ -9,8 +9,8 @@ namespace search { /** - * Keeps track of which elements matched the query for a set of struct - * fields across multiple documents. + * Keeps track of which elements matched the query for a set of fields + * across multiple documents. **/ class MatchingElements { @@ -26,8 +26,8 @@ public: using UP = std::unique_ptr<MatchingElements>; - void add_matching_elements(uint32_t docid, const vespalib::string &struct_field_name, const std::vector<uint32_t> &elements); - const std::vector<uint32_t> &get_matching_elements(uint32_t docid, const vespalib::string &struct_field_name) const; + void add_matching_elements(uint32_t docid, const vespalib::string &field_name, const std::vector<uint32_t> &elements); + const std::vector<uint32_t> &get_matching_elements(uint32_t docid, const vespalib::string &field_name) const; }; } // namespace search diff --git a/searchlib/src/vespa/searchlib/common/matching_elements_fields.cpp b/searchlib/src/vespa/searchlib/common/matching_elements_fields.cpp new file mode 100644 index 00000000000..b36e1eb333e --- /dev/null +++ b/searchlib/src/vespa/searchlib/common/matching_elements_fields.cpp @@ -0,0 +1,10 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "matching_elements_fields.h" + +namespace search { + +MatchingElementsFields::MatchingElementsFields() = default; +MatchingElementsFields::~MatchingElementsFields() = default; + +} // namespace search diff --git a/searchlib/src/vespa/searchlib/common/matching_elements_fields.h b/searchlib/src/vespa/searchlib/common/matching_elements_fields.h new file mode 100644 index 00000000000..f8bb0f373fe --- /dev/null +++ b/searchlib/src/vespa/searchlib/common/matching_elements_fields.h @@ -0,0 +1,51 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/vespalib/stllike/string.h> +#include <set> +#include <map> + +namespace search { + +/** + * Keeps track of a set of field names to calculate MatchingElements for. + * + * Also has mapping of the full name of struct fields into the name of the enclosing field. + * Example: + * A map<string, string> field "my_map" could contain two struct fields: "my_map.key" and "my_map.value". + **/ +class MatchingElementsFields { +private: + std::set<vespalib::string> _fields; + std::map<vespalib::string, vespalib::string> _struct_fields; + +public: + MatchingElementsFields(); + ~MatchingElementsFields(); + bool empty() const { return _fields.empty(); } + void add_field(const vespalib::string &field_name) { + _fields.insert(field_name); + } + void add_mapping(const vespalib::string &field_name, + const vespalib::string &struct_field_name) { + _fields.insert(field_name); + _struct_fields[struct_field_name] = field_name; + } + bool has_field(const vespalib::string &field_name) const { + return (_fields.count(field_name) > 0); + } + bool has_struct_field(const vespalib::string &struct_field_name) const { + return (_struct_fields.find(struct_field_name) != _struct_fields.end()); + } + const vespalib::string &get_enclosing_field(const vespalib::string &struct_field_name) const { + static const vespalib::string empty; + auto res = _struct_fields.find(struct_field_name); + if (res == _struct_fields.end()) { + return empty; + } + return res->second; + } +}; + +} // namespace search diff --git a/searchlib/src/vespa/searchlib/common/struct_field_mapper.cpp b/searchlib/src/vespa/searchlib/common/struct_field_mapper.cpp deleted file mode 100644 index 849cfd06ade..00000000000 --- a/searchlib/src/vespa/searchlib/common/struct_field_mapper.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "struct_field_mapper.h" - -namespace search { - -StructFieldMapper::StructFieldMapper() = default; -StructFieldMapper::~StructFieldMapper() = default; - -} // namespace search diff --git a/searchlib/src/vespa/searchlib/common/struct_field_mapper.h b/searchlib/src/vespa/searchlib/common/struct_field_mapper.h deleted file mode 100644 index 1d0604daec3..00000000000 --- a/searchlib/src/vespa/searchlib/common/struct_field_mapper.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/vespalib/stllike/string.h> -#include <set> -#include <map> - -namespace search { - -/** - * Keeps track of a set of struct field names and enables mapping the - * full name of struct subfields into the name of the enclosing struct - * field. - **/ -class StructFieldMapper -{ -private: - std::set<vespalib::string> _struct_fields; - std::map<vespalib::string,vespalib::string> _struct_subfields; - -public: - StructFieldMapper(); - ~StructFieldMapper(); - bool empty() const { return _struct_fields.empty(); } - void add_mapping(const vespalib::string &struct_field_name, - const vespalib::string &struct_subfield_name) - { - _struct_fields.insert(struct_field_name); - _struct_subfields[struct_subfield_name] = struct_field_name; - } - bool is_struct_field(const vespalib::string &field_name) const { - return (_struct_fields.count(field_name) > 0); - } - bool is_struct_subfield(const vespalib::string &field_name) const { - return (_struct_subfields.find(field_name) != _struct_subfields.end()); - } - const vespalib::string &get_struct_field(const vespalib::string &struct_subfield_name) const { - static const vespalib::string empty; - auto res = _struct_subfields.find(struct_subfield_name); - if (res == _struct_subfields.end()) { - return empty; - } - return res->second; - } -}; - -} // namespace search diff --git a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp index d1e0a2528e7..ac4f164b09f 100644 --- a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp @@ -11,12 +11,12 @@ namespace search::queryeval { -SameElementBlueprint::SameElementBlueprint(const vespalib::string &struct_field_name_in, bool expensive) +SameElementBlueprint::SameElementBlueprint(const vespalib::string &field_name_in, bool expensive) : ComplexLeafBlueprint(FieldSpecBaseList()), _estimate(), _layout(), _terms(), - _struct_field_name(struct_field_name_in) + _field_name(field_name_in) { if (expensive) { set_cost_tier(State::COST_TIER_EXPENSIVE); diff --git a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h index fc19abe4c5e..8d647ac3a32 100644 --- a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h @@ -17,10 +17,10 @@ private: HitEstimate _estimate; fef::MatchDataLayout _layout; std::vector<Blueprint::UP> _terms; - vespalib::string _struct_field_name; + vespalib::string _field_name; public: - SameElementBlueprint(const vespalib::string &struct_field_name_in, bool expensive); + SameElementBlueprint(const vespalib::string &field_name_in, bool expensive); SameElementBlueprint(const SameElementBlueprint &) = delete; SameElementBlueprint &operator=(const SameElementBlueprint &) = delete; ~SameElementBlueprint(); @@ -42,7 +42,7 @@ public: bool strict) const override; void visitMembers(vespalib::ObjectVisitor &visitor) const override; const std::vector<Blueprint::UP> &terms() const { return _terms; } - const vespalib::string &struct_field_name() const { return _struct_field_name; } + const vespalib::string &field_name() const { return _field_name; } }; } |