aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@online.no>2024-03-06 16:06:38 +0100
committerTor Egge <Tor.Egge@online.no>2024-03-06 16:08:10 +0100
commit0340d45620f555d5daae08016ba85663b88d165c (patch)
tree034ab941bc0eea0da41ec3d40a1e2a3786c99aba /searchlib
parent296c4a2be1e8a0d521c036eb30a709364ceacc57 (diff)
Add interpolated lookup for streaming search.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java1
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedDocumentFieldLookupNode.java42
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedLookupNode.java4
-rw-r--r--searchlib/src/vespa/searchlib/aggregation/modifiers.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/common/identifiable.h2
-rw-r--r--searchlib/src/vespa/searchlib/expression/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/expression/documentfieldnode.h4
-rw-r--r--searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.cpp133
-rw-r--r--searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.h33
-rw-r--r--searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.h1
11 files changed, 236 insertions, 1 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java
index 840fb43cfa0..c5fd6e5c68f 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/ForceLoad.java
@@ -46,6 +46,7 @@ public class ForceLoad {
"ExpressionNode",
"AggregationRefNode",
"IntegerResultNode",
+ "InterpolatedDocumentFieldLookupNode",
"Int32ResultNode",
"Int16ResultNode",
"Int8ResultNode",
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedDocumentFieldLookupNode.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedDocumentFieldLookupNode.java
new file mode 100644
index 00000000000..15605eb4d68
--- /dev/null
+++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedDocumentFieldLookupNode.java
@@ -0,0 +1,42 @@
+package com.yahoo.searchlib.expression;
+
+import com.yahoo.vespa.objects.ObjectVisitor;
+
+/*
+ * Streaming search version of InterpolatedLookupNode.
+ */
+public class InterpolatedDocumentFieldLookupNode extends InterpolatedLookupNode {
+ public static final int classId = registerClass(0x4000 + 166, InterpolatedDocumentFieldLookupNode.class, InterpolatedDocumentFieldLookupNode::new);
+
+ /**
+ * Constructs an empty result node.
+ * <b>NOTE:</b> This instance is broken until non-optional member data is set.
+ */
+ public InterpolatedDocumentFieldLookupNode() {
+ super();
+ }
+
+ /**
+ * Constructs an instance of this class with given field name
+ * and lookup argument.
+ *
+ * @param field The field to retrieve.
+ * @param arg Expression evaluating to the lookup argument.
+ */
+ public InterpolatedDocumentFieldLookupNode(String field, ExpressionNode arg) {
+ super(field, arg);
+ }
+
+ @Override
+ protected int onGetClassId() {
+ return classId;
+ }
+
+ public String getFieldName() { return super.getAttributeName(); }
+
+ @Override
+ public void visitMembers(ObjectVisitor visitor) {
+ super.visitSuperMembers(visitor);
+ visitor.visit("field", getFieldName());
+ }
+}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedLookupNode.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedLookupNode.java
index e8ebfad0b0d..73626a8f5f0 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedLookupNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/InterpolatedLookupNode.java
@@ -91,4 +91,8 @@ public class InterpolatedLookupNode extends UnaryFunctionNode {
visitor.visit("attribute", attribute);
}
+ protected void visitSuperMembers(ObjectVisitor visitor) {
+ super.visitMembers(visitor);
+ }
+
}
diff --git a/searchlib/src/vespa/searchlib/aggregation/modifiers.cpp b/searchlib/src/vespa/searchlib/aggregation/modifiers.cpp
index d2a27b7bedd..81664ce66eb 100644
--- a/searchlib/src/vespa/searchlib/aggregation/modifiers.cpp
+++ b/searchlib/src/vespa/searchlib/aggregation/modifiers.cpp
@@ -6,6 +6,8 @@
#include <vespa/searchlib/expression/attributenode.h>
#include <vespa/searchlib/expression/attribute_map_lookup_node.h>
#include <vespa/searchlib/expression/documentfieldnode.h>
+#include <vespa/searchlib/expression/interpolated_document_field_lookup_node.h>
+#include <vespa/searchlib/expression/interpolatedlookupfunctionnode.h>
using namespace search::expression;
@@ -63,6 +65,10 @@ AttributeNodeReplacer::execute(vespalib::Identifiable &obj)
std::unique_ptr<ExpressionNode>
Attribute2DocumentAccessor::getReplacementNode(const AttributeNode &attributeNode)
{
+ if (attributeNode.inherits(InterpolatedLookup::classId)) {
+ auto& interpolated_lookup = static_cast<const InterpolatedLookup&>(attributeNode);
+ return std::make_unique<InterpolatedDocumentFieldLookupNode>(interpolated_lookup.getAttributeName(), interpolated_lookup.clone_lookup_expression());
+ }
return std::make_unique<DocumentFieldNode>(attributeNode.getAttributeName());
}
diff --git a/searchlib/src/vespa/searchlib/common/identifiable.h b/searchlib/src/vespa/searchlib/common/identifiable.h
index 4576f24f065..b80e1d5de2f 100644
--- a/searchlib/src/vespa/searchlib/common/identifiable.h
+++ b/searchlib/src/vespa/searchlib/common/identifiable.h
@@ -172,5 +172,7 @@
#define CID_TensorAttribute SEARCHLIB_CID(164)
#define CID_ReferenceAttribute SEARCHLIB_CID(165)
+#define CID_search_expression_InterpolatedDocumentFieldLookupNode SEARCHLIB_CID(166)
+
#define CID_search_NormalSketch SEARCHLIB_CID(170)
#define CID_search_SparseSketch SEARCHLIB_CID(171)
diff --git a/searchlib/src/vespa/searchlib/expression/CMakeLists.txt b/searchlib/src/vespa/searchlib/expression/CMakeLists.txt
index 11c0b478e23..5c6039a1b5f 100644
--- a/searchlib/src/vespa/searchlib/expression/CMakeLists.txt
+++ b/searchlib/src/vespa/searchlib/expression/CMakeLists.txt
@@ -25,6 +25,7 @@ vespa_add_library(searchlib_expression OBJECT
mathfunctionnode.cpp
numericfunctionnode.cpp
resultnode.cpp
+ interpolated_document_field_lookup_node.cpp
interpolatedlookupfunctionnode.cpp
functionnodes.cpp
resultnodes.cpp
diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
index 1362234d4a4..915f6de5c6c 100644
--- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
+++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
@@ -40,7 +40,7 @@ public:
DocumentFieldNode(DocumentFieldNode && rhs) noexcept = default;
DocumentFieldNode & operator = (DocumentFieldNode && rhs) noexcept = default;
const vespalib::string & getFieldName() const override { return _fieldName; }
-private:
+public:
class Handler : public document::fieldvalue::IteratorHandler {
public:
virtual void reset() = 0;
@@ -48,6 +48,7 @@ private:
void onCollectionStart(const Content & c) override;
void onStructStart(const Content & c) override;
};
+private:
class SingleHandler : public Handler {
public:
SingleHandler(ResultNode & result) : _result(result) {}
@@ -71,6 +72,7 @@ private:
bool onExecute() const override;
void onDoc(const document::Document & doc) override;
void onDocType(const document::DocumentType & docType) override;
+protected:
document::FieldPath _fieldPath;
mutable ResultNode::CP _value;
mutable std::unique_ptr<Handler> _handler;
diff --git a/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.cpp b/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.cpp
new file mode 100644
index 00000000000..a00465c9144
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.cpp
@@ -0,0 +1,133 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "interpolated_document_field_lookup_node.h"
+#include "simple_interpolate.h"
+#include <vespa/document/fieldvalue/document.h>
+
+using vespalib::Serializer;
+using vespalib::Deserializer;
+
+namespace search::expression {
+
+namespace {
+
+class InterpolateHandler : public InterpolatedDocumentFieldLookupNode::Handler {
+ std::vector<double>& _values;
+public:
+ InterpolateHandler(std::vector<double>& values);
+ ~InterpolateHandler() override;
+ void reset() override;
+ void onPrimitive(uint32_t fid, const Content& c) override;
+};
+
+InterpolateHandler::InterpolateHandler(std::vector<double>& values)
+ : InterpolatedDocumentFieldLookupNode::Handler(),
+ _values(values)
+{
+}
+
+InterpolateHandler::~InterpolateHandler() = default;
+
+void
+InterpolateHandler::reset()
+{
+}
+
+void
+InterpolateHandler::onPrimitive(uint32_t, const Content& c)
+{
+ _values.push_back(c.getValue().getAsDouble());
+}
+
+}
+
+IMPLEMENT_EXPRESSIONNODE(InterpolatedDocumentFieldLookupNode, DocumentFieldNode);
+
+InterpolatedDocumentFieldLookupNode::InterpolatedDocumentFieldLookupNode() noexcept
+ : DocumentFieldNode(),
+ _lookup_expression(),
+ _values(),
+ _float_result()
+{
+}
+
+InterpolatedDocumentFieldLookupNode::InterpolatedDocumentFieldLookupNode(vespalib::stringref name, std::unique_ptr<ExpressionNode> arg)
+ : DocumentFieldNode(name),
+ _lookup_expression(std::move(arg)),
+ _values(),
+ _float_result()
+{
+}
+
+InterpolatedDocumentFieldLookupNode::InterpolatedDocumentFieldLookupNode(const InterpolatedDocumentFieldLookupNode &rhs) = default;
+
+InterpolatedDocumentFieldLookupNode::~InterpolatedDocumentFieldLookupNode() = default;
+
+InterpolatedDocumentFieldLookupNode&
+InterpolatedDocumentFieldLookupNode::operator=(const InterpolatedDocumentFieldLookupNode &rhs) = default;
+
+Serializer &
+InterpolatedDocumentFieldLookupNode::onSerialize(Serializer & os) const
+{
+ os << _value;
+ os << uint32_t(1) << _lookup_expression;
+ os << _fieldName;
+ return os;
+}
+
+Deserializer &
+InterpolatedDocumentFieldLookupNode::onDeserialize(Deserializer & is)
+{
+ is >> _value;
+ uint32_t count(0);
+ is >> count;
+ if (count > 0) {
+ is >> _lookup_expression;
+ } else {
+ _lookup_expression.reset();
+ }
+ is >> _fieldName;
+ return is;
+}
+
+void
+InterpolatedDocumentFieldLookupNode::visitMembers(vespalib::ObjectVisitor & visitor) const
+{
+ DocumentFieldNode::visitMembers(visitor);
+ visit(visitor, "index", *_lookup_expression);
+}
+
+void
+InterpolatedDocumentFieldLookupNode::selectMembers(const vespalib::ObjectPredicate & predicate, vespalib::ObjectOperation & operation)
+{
+ DocumentFieldNode::selectMembers(predicate, operation);
+ if (_lookup_expression) {
+ _lookup_expression->select(predicate, operation);
+ }
+}
+
+void
+InterpolatedDocumentFieldLookupNode::onPrepare(bool)
+{
+ _handler = std::make_unique<InterpolateHandler>(_values);
+ _value = std::make_unique<FloatResultNode>();
+}
+
+bool
+InterpolatedDocumentFieldLookupNode::onExecute() const
+{
+ if (_lookup_expression) {
+ _values.clear();
+ _doc->iterateNested(_fieldPath.getFullRange(), *_handler);
+ _lookup_expression->execute();
+ auto lookup = _lookup_expression->getResult()->getFloat();
+ auto result = simple_interpolate(_values, lookup);
+ _float_result.set(result);
+ } else {
+ _float_result.set(0.0);
+ }
+ _value->set(_float_result);
+ return true;
+}
+
+}
diff --git a/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.h b/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.h
new file mode 100644
index 00000000000..69f0849cf20
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/expression/interpolated_document_field_lookup_node.h
@@ -0,0 +1,33 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include "documentfieldnode.h"
+
+namespace search::expression {
+
+/*
+ * Interpolated lookup for streaming search.
+ */
+class InterpolatedDocumentFieldLookupNode : public DocumentFieldNode
+{
+public:
+ DECLARE_EXPRESSIONNODE(InterpolatedDocumentFieldLookupNode);
+ DECLARE_NBO_SERIALIZE;
+
+ InterpolatedDocumentFieldLookupNode() noexcept;
+ InterpolatedDocumentFieldLookupNode(vespalib::stringref name, std::unique_ptr<ExpressionNode> arg);
+ InterpolatedDocumentFieldLookupNode(const InterpolatedDocumentFieldLookupNode& rhs);
+ ~InterpolatedDocumentFieldLookupNode() override;
+ InterpolatedDocumentFieldLookupNode& operator=(const InterpolatedDocumentFieldLookupNode &rhs);
+ void visitMembers(vespalib::ObjectVisitor& visitor) const override;
+ void selectMembers(const vespalib::ObjectPredicate& predicate, vespalib::ObjectOperation& operation) override;
+private:
+ void onPrepare(bool preserveAccurateTypes) override;
+ bool onExecute() const override;
+ vespalib::IdentifiablePtr<ExpressionNode> _lookup_expression;
+ mutable std::vector<double> _values;
+ mutable FloatResultNode _float_result;
+};
+
+}
diff --git a/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp b/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp
index fbc69a512d3..45f4f8e5fb1 100644
--- a/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp
+++ b/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp
@@ -116,4 +116,14 @@ InterpolatedLookup::selectMembers(const vespalib::ObjectPredicate & predicate, v
}
}
+std::unique_ptr<ExpressionNode>
+InterpolatedLookup::clone_lookup_expression() const
+{
+ if (_lookupExpression) {
+ return std::unique_ptr<ExpressionNode>(_lookupExpression->clone());
+ } else {
+ return {};
+ }
+}
+
}
diff --git a/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.h b/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.h
index 8eb05d1f0d1..57b699c821d 100644
--- a/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.h
+++ b/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.h
@@ -21,6 +21,7 @@ public:
InterpolatedLookup & operator= (const InterpolatedLookup &rhs);
void visitMembers(vespalib::ObjectVisitor & visitor) const override;
void selectMembers(const vespalib::ObjectPredicate & predicate, vespalib::ObjectOperation & operation) override;
+ std::unique_ptr<ExpressionNode> clone_lookup_expression() const;
private:
std::pair<std::unique_ptr<ResultNode>, std::unique_ptr<Handler>>
createResultHandler(bool preserveAccurateType, const attribute::IAttributeVector & attribute) const override;