diff options
author | Håvard Pettersen <havardpe@oath.com> | 2018-06-13 13:57:13 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2018-06-13 14:02:25 +0000 |
commit | 7aa433adafa69a27c8b864c77e21c35402891215 (patch) | |
tree | 4f6c199e81122a691e56baad744b2264a80edadc /searchlib | |
parent | 0fefd4e3b3038db6b3b2f573571034d3614816bf (diff) |
enable native dot product to include all fields
Diffstat (limited to 'searchlib')
4 files changed, 48 insertions, 9 deletions
diff --git a/searchlib/src/tests/features/native_dot_product/native_dot_product_test.cpp b/searchlib/src/tests/features/native_dot_product/native_dot_product_test.cpp index 1da912ccb3a..0cf13443142 100644 --- a/searchlib/src/tests/features/native_dot_product/native_dot_product_test.cpp +++ b/searchlib/src/tests/features/native_dot_product/native_dot_product_test.cpp @@ -16,7 +16,8 @@ using namespace search::fef::test; using namespace search::features; using CollectionType = FieldInfo::CollectionType; -const std::string featureName("nativeDotProduct(foo)"); +const std::string fooFeatureName("nativeDotProduct(foo)"); +const std::string anyFeatureName("nativeDotProduct"); struct BlueprintFactoryFixture { BlueprintFactory factory; @@ -78,7 +79,8 @@ struct RankFixture : BlueprintFactoryFixture, IndexFixture { std::vector<TermFieldHandle> fooHandles; std::vector<TermFieldHandle> barHandles; RankFixture(const std::vector<uint32_t> &fooWeights, - const std::vector<uint32_t> &barWeights) + const std::vector<uint32_t> &barWeights, + const vespalib::string &featureName = fooFeatureName) : queryEnv(&indexEnv), rankSetup(factory, indexEnv), mdl(), match_data(), rankProgram(), fooHandles(), barHandles() { @@ -152,6 +154,12 @@ TEST_FF("require that setup fails for unknown field", NativeDotProductBlueprint, EXPECT_TRUE(!((Blueprint&)f1).setup(f2.indexEnv, std::vector<vespalib::string>(1, "unknown"))); } +TEST_FF("require that setup can be done without field", NativeDotProductBlueprint, IndexFixture) { + DummyDependencyHandler deps(f1); + f1.setName(vespalib::make_string("%s", f1.getBaseName().c_str())); + EXPECT_TRUE(((Blueprint&)f1).setup(f2.indexEnv, std::vector<vespalib::string>())); +} + TEST_F("require that not searching a field will give it 0.0 dot product", RankFixture(vec(), vec(1, 2, 3))) { EXPECT_EQUAL(0.0, f1.getScore(10)); } @@ -183,11 +191,18 @@ TEST_F("require that data from other fields is ignored", RankFixture(vec(1, 3), EXPECT_EQUAL(14, f1.getScore(10)); } +TEST_F("require that not specifying field includes all term/field combinations", RankFixture(vec(1, 3), vec(5, 7), anyFeatureName)) { + f1.setFooWeight(0, 10, 2); + f1.setFooWeight(1, 10, 4); + f1.setBarWeight(0, 10, 6); + f1.setBarWeight(1, 10, 8); + EXPECT_EQUAL(100, f1.getScore(10)); +} + TEST_F("require that negative weights in the index works", RankFixture(vec(1, 3), vec())) { f1.setFooWeight(0, 10, 2); f1.setFooWeight(1, 10, -4); EXPECT_EQUAL(-10, f1.getScore(10)); } - TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/vespa/searchlib/features/native_dot_product_feature.cpp b/searchlib/src/vespa/searchlib/features/native_dot_product_feature.cpp index cb8136e8b7f..7865e32849f 100644 --- a/searchlib/src/vespa/searchlib/features/native_dot_product_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/native_dot_product_feature.cpp @@ -8,6 +8,23 @@ using namespace search::fef; namespace search { namespace features { +NativeDotProductExecutor::NativeDotProductExecutor(const search::fef::IQueryEnvironment &env) + : FeatureExecutor(), + _pairs(), + _md(nullptr) +{ + for (uint32_t i = 0; i < env.getNumTerms(); ++i) { + const search::fef::ITermData *td = env.getTerm(i); + auto weight = td->getWeight(); + for (size_t f = 0; f < td->numFields(); ++f) { + auto handle = td->field(f).getHandle(); + if (handle != search::fef::IllegalHandle) { + _pairs.emplace_back(handle, weight); + } + } + } +} + NativeDotProductExecutor::NativeDotProductExecutor(const search::fef::IQueryEnvironment &env, uint32_t fieldId) : FeatureExecutor(), _pairs(), @@ -46,15 +63,21 @@ bool NativeDotProductBlueprint::setup(const IIndexEnvironment &, const ParameterList ¶ms) { - _field = params[0].asField(); - describeOutput("out", "dot product between query term weights and match weights for the given field"); + if (params.size() > 0) { + _field = params[0].asField(); + } + describeOutput("out", "dot product between query term weights and match weights"); return true; } FeatureExecutor & NativeDotProductBlueprint::createExecutor(const IQueryEnvironment &queryEnv, vespalib::Stash &stash) const { - return stash.create<NativeDotProductExecutor>(queryEnv, _field->id()); + if (_field) { + return stash.create<NativeDotProductExecutor>(queryEnv, _field->id()); + } else { + return stash.create<NativeDotProductExecutor>(queryEnv); + } } } // namespace features diff --git a/searchlib/src/vespa/searchlib/features/native_dot_product_feature.h b/searchlib/src/vespa/searchlib/features/native_dot_product_feature.h index a71d23f3158..33c5c89c88b 100644 --- a/searchlib/src/vespa/searchlib/features/native_dot_product_feature.h +++ b/searchlib/src/vespa/searchlib/features/native_dot_product_feature.h @@ -20,6 +20,7 @@ private: void handle_bind_match_data(const fef::MatchData &md) override; public: + NativeDotProductExecutor(const fef::IQueryEnvironment &env); NativeDotProductExecutor(const fef::IQueryEnvironment &env, uint32_t fieldId); void execute(uint32_t docId) override; }; @@ -31,13 +32,13 @@ class NativeDotProductBlueprint : public fef::Blueprint private: const fef::FieldInfo *_field; public: - NativeDotProductBlueprint() : Blueprint("nativeDotProduct"), _field(0) {} + NativeDotProductBlueprint() : Blueprint("nativeDotProduct"), _field(nullptr) {} void visitDumpFeatures(const fef::IIndexEnvironment &, fef::IDumpFeatureVisitor &) const override {} fef::Blueprint::UP createInstance() const override { return Blueprint::UP(new NativeDotProductBlueprint()); } fef::ParameterDescriptions getDescriptions() const override { - return fef::ParameterDescriptions().desc().field(); + return fef::ParameterDescriptions().desc().field().desc(); } bool setup(const fef::IIndexEnvironment &env, const fef::ParameterList ¶ms) override; fef::FeatureExecutor &createExecutor(const fef::IQueryEnvironment &env, vespalib::Stash &stash) const override; diff --git a/searchlib/src/vespa/searchlib/fef/featurenamebuilder.cpp b/searchlib/src/vespa/searchlib/fef/featurenamebuilder.cpp index ec00b7d2f90..0eba912fafd 100644 --- a/searchlib/src/vespa/searchlib/fef/featurenamebuilder.cpp +++ b/searchlib/src/vespa/searchlib/fef/featurenamebuilder.cpp @@ -136,7 +136,7 @@ FeatureNameBuilder::buildName() const vespalib::string ret; if (!_baseName.empty()) { ret = _baseName; - if (!_parameters.empty() > 0) { + if (!_parameters.empty()) { ret += "("; for (uint32_t i = 0; i < _parameters.size(); ++i) { if (i > 0) { |