diff options
author | Håvard Pettersen <havardpe@oath.com> | 2018-05-31 10:32:23 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2018-05-31 13:50:26 +0000 |
commit | 6457b9eb0294204eb9a553c1f1830ff2e3de594b (patch) | |
tree | 7a667585cf9c32d01fcb4a0394fcee0089ed1b6a /searchcore | |
parent | ac9c5c9f7656c55a8d2a014a4e1dc02c1b2caf5f (diff) |
build same element blueprint
Diffstat (limited to 'searchcore')
6 files changed, 196 insertions, 12 deletions
diff --git a/searchcore/src/tests/proton/matching/matching_test.cpp b/searchcore/src/tests/proton/matching/matching_test.cpp index 62c61406f67..a770fff3f5f 100644 --- a/searchcore/src/tests/proton/matching/matching_test.cpp +++ b/searchcore/src/tests/proton/matching/matching_test.cpp @@ -61,6 +61,36 @@ void inject_match_phase_limiting(Properties &setup, const vespalib::string &attr setup.import(cfg); } +FakeResult make_elem_result(const std::vector<std::pair<uint32_t,std::vector<uint32_t> > > &match_data) { + FakeResult result; + uint32_t pos_should_be_ignored = 0; + for (const auto &doc: match_data) { + result.doc(doc.first); + for (const auto &elem: doc.second) { + result.elem(elem).pos(++pos_should_be_ignored); + } + } + return result; +} + +vespalib::string make_simple_stack_dump(const vespalib::string &field, + const vespalib::string &term) +{ + QueryBuilder<ProtonNodeTypes> builder; + builder.addStringTerm(term, field, 1, search::query::Weight(1)); + return StackDumpCreator::create(*builder.build()); +} + +vespalib::string make_same_element_stack_dump(const vespalib::string &a1_term, + const vespalib::string &f1_term) +{ + QueryBuilder<ProtonNodeTypes> builder; + builder.addSameElement(2, "ignored field name"); + builder.addStringTerm(a1_term, "a1", 1, search::query::Weight(1)); + builder.addStringTerm(f1_term, "f1", 2, search::query::Weight(1)); + return StackDumpCreator::create(*builder.build()); +} + //----------------------------------------------------------------------------- const uint32_t NUM_DOCS = 1000; @@ -238,6 +268,13 @@ struct MyWorld { searchContext.attr().addResult("a1", term, result); } + void add_same_element_results(const vespalib::string &a1_term, const vespalib::string &f1_0_term) { + auto a1_result = make_elem_result({{10, {1}}, {20, {2}}, {21, {2}}}); + auto f1_0_result = make_elem_result({{10, {2}}, {20, {2}}, {21, {2}}}); + searchContext.attr().addResult("a1", a1_term, a1_result); + searchContext.idx(0).getFake().addResult("f1", f1_0_term, f1_0_result); + } + void basicResults() { searchContext.idx(0).getFake().addResult("f1", "foo", FakeResult() @@ -249,26 +286,32 @@ struct MyWorld { .doc(600).doc(700).doc(800).doc(900)); } - void setStackDump(Request &request, const vespalib::string &field, - const vespalib::string &term) { - QueryBuilder<ProtonNodeTypes> builder; - builder.addStringTerm(term, field, 1, search::query::Weight(1)); - vespalib::string stack_dump = - StackDumpCreator::create(*builder.build()); + void setStackDump(Request &request, const vespalib::string &stack_dump) { request.stackDump.assign(stack_dump.data(), stack_dump.data() + stack_dump.size()); } - SearchRequest::SP createSimpleRequest(const vespalib::string &field, - const vespalib::string &term) + SearchRequest::SP createRequest(const vespalib::string &stack_dump) { SearchRequest::SP request(new SearchRequest); request->setTimeout(60 * fastos::TimeStamp::SEC); - setStackDump(*request, field, term); + setStackDump(*request, stack_dump); request->maxhits = 10; return request; } + SearchRequest::SP createSimpleRequest(const vespalib::string &field, + const vespalib::string &term) + { + return createRequest(make_simple_stack_dump(field, term)); + } + + SearchRequest::SP createSameElementRequest(const vespalib::string &a1_term, + const vespalib::string &f1_term) + { + return createRequest(make_same_element_stack_dump(a1_term, f1_term)); + } + Matcher::SP createMatcher() { return std::make_shared<Matcher>(schema, config, clock, queryLimiter, constantValueRepo, 0); } @@ -317,7 +360,7 @@ struct MyWorld { const vespalib::string & term) { DocsumRequest::SP request(new DocsumRequest); - setStackDump(*request, field, term); + setStackDump(*request, make_simple_stack_dump(field, term)); // match a subset of basic result + request for a non-hit (not // sorted on docid) @@ -800,4 +843,14 @@ TEST("require that fields are tagged with data type") { EXPECT_EQUAL(predicate_field->get_data_type(), FieldInfo::DataType::BOOLEANTREE); } +TEST("require that same element search works (note that this does not test/use the attribute element iterator wrapper)") { + MyWorld world; + world.basicSetup(); + world.add_same_element_results("foo", "bar"); + SearchRequest::SP request = world.createSameElementRequest("foo", "bar"); + SearchReply::UP reply = world.performSearch(request, 1); + ASSERT_EQUAL(1u, reply->hits.size()); + EXPECT_EQUAL(document::DocumentId("doc::20").getGlobalId(), reply->hits[0].gid); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchcore/src/vespa/searchcore/proton/matching/CMakeLists.txt b/searchcore/src/vespa/searchcore/proton/matching/CMakeLists.txt index 78084f29742..0dee7adfa49 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/CMakeLists.txt +++ b/searchcore/src/vespa/searchcore/proton/matching/CMakeLists.txt @@ -27,6 +27,7 @@ vespa_add_library(searchcore_matching STATIC ranking_constants.cpp requestcontext.cpp result_processor.cpp + same_element_builder.cpp search_session.cpp session_manager_explorer.cpp sessionmanager.cpp diff --git a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp index 165fc67179a..268fe63ba4c 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp @@ -2,6 +2,8 @@ #include "querynodes.h" #include "blueprintbuilder.h" +#include "termdatafromnode.h" +#include "same_element_builder.h" #include <vespa/searchlib/query/tree/customtypevisitor.h> #include <vespa/searchlib/queryeval/leaf_blueprints.h> #include <vespa/searchlib/queryeval/intermediate_blueprints.h> @@ -98,6 +100,15 @@ private: n.setDocumentFrequency(_result->getState().estimate().estHits, _context.getDocIdLimit()); } + void buildSameElement(ProtonSameElement &n) { + SameElementBuilder builder(_requestContext, _context); + for (size_t i = 0; i < n.getChildren().size(); ++i) { + search::query::Node &node = *n.getChildren()[i]; + builder.add_child(node); + } + _result = builder.build(); + } + template <typename NodeType> void buildTerm(NodeType &n) { FieldSpecList indexFields; @@ -131,7 +142,7 @@ protected: void visit(ProtonRank &n) override { buildIntermediate(new RankBlueprint(), n); } void visit(ProtonNear &n) override { buildIntermediate(new NearBlueprint(n.getDistance()), n); } void visit(ProtonONear &n) override { buildIntermediate(new ONearBlueprint(n.getDistance()), n); } - void visit(ProtonSameElement &n) override { buildIntermediate(nullptr /*new SameElementBlueprint())*/, n); } + void visit(ProtonSameElement &n) override { buildSameElement(n); } void visit(ProtonWeightedSetTerm &n) override { buildTerm(n); } diff --git a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.h b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.h index eb45a735780..44cd6ffabfd 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.h +++ b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.h @@ -20,4 +20,3 @@ struct BlueprintBuilder { }; } - diff --git a/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp new file mode 100644 index 00000000000..d3a0ec4726f --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp @@ -0,0 +1,96 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "same_element_builder.h" +#include "querynodes.h" +#include <vespa/searchlib/query/tree/customtypevisitor.h> +#include <vespa/searchlib/queryeval/leaf_blueprints.h> + +using search::queryeval::Blueprint; +using search::queryeval::EmptyBlueprint; +using search::queryeval::FieldSpecList; +using search::queryeval::IRequestContext; +using search::queryeval::SameElementBlueprint; +using search::queryeval::Searchable; + +namespace proton::matching { + +namespace { + +class SameElementBuilderVisitor : public search::query::CustomTypeVisitor<ProtonNodeTypes> +{ +private: + const IRequestContext &_requestContext; + ISearchContext &_context; + SameElementBlueprint &_result; + +public: + SameElementBuilderVisitor(const IRequestContext &requestContext, ISearchContext &context, SameElementBlueprint &result) + : _requestContext(requestContext), + _context(context), + _result(result) {} + + template <class TermNode> + void visitTerm(const TermNode &n) { + if (n.numFields() == 1) { + const ProtonTermData::FieldEntry &field = n.field(0); + assert(field.getFieldId() != search::fef::IllegalFieldId); + assert(field.getHandle() == search::fef::IllegalHandle); + FieldSpecList field_spec; + field_spec.add(_result.getNextChildField(field.field_name, field.getFieldId())); + Searchable &searchable = field.attribute_field ? _context.getAttributes() : _context.getIndexes(); + _result.addTerm(searchable.createBlueprint(_requestContext, field_spec, n)); + } + } + + void visit(ProtonAnd &) override {} + void visit(ProtonAndNot &) override {} + void visit(ProtonNear &) override {} + void visit(ProtonONear &) override {} + void visit(ProtonOr &) override {} + void visit(ProtonRank &) override {} + void visit(ProtonWeakAnd &) override {} + void visit(ProtonSameElement &) override {} + + void visit(ProtonWeightedSetTerm &) override {} + void visit(ProtonDotProduct &) override {} + void visit(ProtonWandTerm &) override {} + void visit(ProtonPhrase &) override {} + void visit(ProtonEquiv &) override {} + + void visit(ProtonNumberTerm &n) override { visitTerm(n); } + void visit(ProtonLocationTerm &n) override { visitTerm(n); } + void visit(ProtonPrefixTerm &n) override { visitTerm(n); } + void visit(ProtonRangeTerm &n) override { visitTerm(n); } + void visit(ProtonStringTerm &n) override { visitTerm(n); } + void visit(ProtonSubstringTerm &n) override { visitTerm(n); } + void visit(ProtonSuffixTerm &n) override { visitTerm(n); } + void visit(ProtonPredicateQuery &) override {} + void visit(ProtonRegExpTerm &n) override { visitTerm(n); } +}; + +} // namespace proton::matching::<unnamed> + +SameElementBuilder::SameElementBuilder(const search::queryeval::IRequestContext &requestContext, ISearchContext &context) + : _requestContext(requestContext), + _context(context), + _result(std::make_unique<SameElementBlueprint>()) +{ +} + +void +SameElementBuilder::add_child(search::query::Node &node) +{ + SameElementBuilderVisitor visitor(_requestContext, _context, *_result); + node.accept(visitor); +} + +Blueprint::UP +SameElementBuilder::build() +{ + if (!_result || _result->terms().empty()) { + return std::make_unique<EmptyBlueprint>(); + } + return std::move(_result); +} + +} // namespace proton::matching diff --git a/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.h b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.h new file mode 100644 index 00000000000..945bb9a97f6 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.h @@ -0,0 +1,24 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "isearchcontext.h" +#include <vespa/searchlib/query/tree/node.h> +#include <vespa/searchlib/queryeval/blueprint.h> +#include <vespa/searchlib/queryeval/same_element_blueprint.h> + +namespace proton::matching { + +class SameElementBuilder +{ +private: + const search::queryeval::IRequestContext &_requestContext; + ISearchContext &_context; + std::unique_ptr<search::queryeval::SameElementBlueprint> _result; +public: + SameElementBuilder(const search::queryeval::IRequestContext &requestContext, ISearchContext &context); + void add_child(search::query::Node &node); + search::queryeval::Blueprint::UP build(); +}; + +} |