summaryrefslogtreecommitdiffstats
path: root/searchcore
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2018-05-31 10:32:23 +0000
committerHåvard Pettersen <havardpe@oath.com>2018-05-31 13:50:26 +0000
commit6457b9eb0294204eb9a553c1f1830ff2e3de594b (patch)
tree7a667585cf9c32d01fcb4a0394fcee0089ed1b6a /searchcore
parentac9c5c9f7656c55a8d2a014a4e1dc02c1b2caf5f (diff)
build same element blueprint
Diffstat (limited to 'searchcore')
-rw-r--r--searchcore/src/tests/proton/matching/matching_test.cpp73
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/CMakeLists.txt1
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp13
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.h1
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp96
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/same_element_builder.h24
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();
+};
+
+}