diff options
author | Alexey Chernyshev <aleksei@spotify.com> | 2022-04-04 16:23:07 +0200 |
---|---|---|
committer | Alexey Chernyshev <aleksei@spotify.com> | 2022-04-07 14:44:30 +0200 |
commit | 7e9b33401201db9a9e22971dd419247e268bbfaa (patch) | |
tree | f5032a82e9fa74247b2fdeb3dcde4dc6cf98ce89 /searchlib | |
parent | ad7cc1d11f0c19baa2344a643377576c559555f7 (diff) |
Propagating annotations for fuzzy query
Diffstat (limited to 'searchlib')
19 files changed, 112 insertions, 26 deletions
diff --git a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp index aa64e944baa..947e4aa30c2 100644 --- a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp +++ b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp @@ -402,7 +402,8 @@ SearchContextTest::buildTermQuery(std::vector<char> & buffer, const vespalib::st { uint32_t indexLen = index.size(); uint32_t termLen = term.size(); - uint32_t queryPacketSize = 1 + 2 * 4 + indexLen + termLen; + uint32_t fuzzyParametersSize = (termType == TermType::FUZZYTERM) ? 8 : 0; + uint32_t queryPacketSize = 1 + 2 * 4 + indexLen + termLen + fuzzyParametersSize; uint32_t p = 0; buffer.resize(queryPacketSize); switch (termType) { @@ -419,6 +420,12 @@ SearchContextTest::buildTermQuery(std::vector<char> & buffer, const vespalib::st p += vespalib::compress::Integer::compressPositive(termLen, &buffer[p]); memcpy(&buffer[p], term.c_str(), termLen); p += termLen; + + if (termType == TermType::FUZZYTERM) { + p += vespalib::compress::Integer::compressPositive(2, &buffer[p]); // max edit distance + p += vespalib::compress::Integer::compressPositive(0, &buffer[p]); // prefix length + } + buffer.resize(p); } diff --git a/searchlib/src/tests/attribute/stringattribute/stringattribute_test.cpp b/searchlib/src/tests/attribute/stringattribute/stringattribute_test.cpp index 1f570e0a381..4deb287df0e 100644 --- a/searchlib/src/tests/attribute/stringattribute/stringattribute_test.cpp +++ b/searchlib/src/tests/attribute/stringattribute/stringattribute_test.cpp @@ -388,8 +388,8 @@ testSingleValue(Attribute & svsa, Config &cfg) TEST("testSingleValue") { EXPECT_EQUAL(24u, sizeof(SearchContext)); - EXPECT_EQUAL(56u, sizeof(StringSearchHelper)); - EXPECT_EQUAL(104u, sizeof(attribute::SingleStringEnumSearchContext)); + EXPECT_EQUAL(88u, sizeof(StringSearchHelper)); + EXPECT_EQUAL(136u, sizeof(attribute::SingleStringEnumSearchContext)); { Config cfg(BasicType::STRING, CollectionType::SINGLE); SingleValueStringAttribute svsa("svsa", cfg); diff --git a/searchlib/src/tests/query/customtypevisitor_test.cpp b/searchlib/src/tests/query/customtypevisitor_test.cpp index 0e8155e23c3..b1e979b5bcb 100644 --- a/searchlib/src/tests/query/customtypevisitor_test.cpp +++ b/searchlib/src/tests/query/customtypevisitor_test.cpp @@ -36,7 +36,7 @@ struct MyRangeTerm : InitTerm<RangeTerm> {}; struct MyStringTerm : InitTerm<StringTerm> {}; struct MySubstrTerm : InitTerm<SubstringTerm> {}; struct MySuffixTerm : InitTerm<SuffixTerm> {}; -struct MyFuzzyTerm : InitTerm<FuzzyTerm> {}; +struct MyFuzzyTerm : FuzzyTerm { MyFuzzyTerm(): FuzzyTerm("term", "view", 0, Weight(0), 2, 0) {} }; struct MyWeakAnd : WeakAnd { MyWeakAnd() : WeakAnd(1234, "view") {} }; struct MyWeightedSetTerm : WeightedSetTerm { MyWeightedSetTerm() : WeightedSetTerm(0, "view", 0, Weight(42)) {} }; struct MyDotProduct : DotProduct { MyDotProduct() : DotProduct(0, "view", 0, Weight(42)) {} }; diff --git a/searchlib/src/tests/query/query_visitor_test.cpp b/searchlib/src/tests/query/query_visitor_test.cpp index f770213e8e5..8e8be997be0 100644 --- a/searchlib/src/tests/query/query_visitor_test.cpp +++ b/searchlib/src/tests/query/query_visitor_test.cpp @@ -86,7 +86,7 @@ TEST("requireThatAllNodesCanBeVisited") { checkVisit<NearestNeighborTerm>(new SimpleNearestNeighborTerm("query_tensor", "doc_tensor", 0, Weight(0), 123, true, 321, 100100.25)); checkVisit<TrueQueryNode>(new SimpleTrue()); checkVisit<FalseQueryNode>(new SimpleFalse()); - checkVisit<FuzzyTerm>(new SimpleFuzzyTerm("t", "field", 0, Weight(0))); + checkVisit<FuzzyTerm>(new SimpleFuzzyTerm("t", "field", 0, Weight(0), 2, 0)); } } // namespace diff --git a/searchlib/src/tests/query/querybuilder_test.cpp b/searchlib/src/tests/query/querybuilder_test.cpp index 2ea566027c4..5b410879fa0 100644 --- a/searchlib/src/tests/query/querybuilder_test.cpp +++ b/searchlib/src/tests/query/querybuilder_test.cpp @@ -7,6 +7,8 @@ #include <vespa/searchlib/query/tree/querybuilder.h> #include <vespa/searchlib/query/tree/simplequery.h> #include <vespa/searchlib/query/tree/stackdumpcreator.h> +#include <vespa/searchlib/query/query_term_decoder.h> +#include <vespa/searchlib/query/query_term_simple.h> #include <vespa/vespalib/testkit/test_kit.h> #include <vespa/log/log.h> @@ -115,7 +117,7 @@ Node::UP createQueryTree() { builder.add_true_node(); builder.add_false_node(); } - builder.addFuzzyTerm(str[5], view[5], id[5], weight[5]); + builder.addFuzzyTerm(str[5], view[5], id[5], weight[5], 3, 1); } Node::UP node = builder.build(); ASSERT_TRUE(node.get()); @@ -311,6 +313,8 @@ void checkQueryTreeTypes(Node *node) { auto* fuzzy_term = as_node<FuzzyTerm>(and_node->getChildren()[12]); EXPECT_TRUE(checkTerm(fuzzy_term, str[5], view[5], id[5], weight[5])); + EXPECT_EQUAL(3u, fuzzy_term->getMaxEditDistance()); + EXPECT_EQUAL(1u, fuzzy_term->getPrefixLength()); } struct AbstractTypes { @@ -434,8 +438,9 @@ struct MyNearestNeighborTerm : NearestNeighborTerm { struct MyTrue : TrueQueryNode {}; struct MyFalse : FalseQueryNode {}; struct MyFuzzyTerm : FuzzyTerm { - MyFuzzyTerm(const Type &t, const string &f, int32_t i, Weight w) - : FuzzyTerm(t, f, i, w) { + MyFuzzyTerm(const Type &t, const string &f, int32_t i, Weight w, + uint32_t m, uint32_t p) + : FuzzyTerm(t, f, i, w, m, p) { } }; @@ -578,6 +583,7 @@ TEST("require that Query Tree Creator Can Replicate Queries") { TEST("require that Query Tree Creator Can Create Queries From Stack") { Node::UP node = createQueryTree<MyQueryNodeTypes>(); string stackDump = StackDumpCreator::create(*node); + SimpleQueryStackDumpIterator iterator(stackDump); Node::UP new_node = QueryTreeCreator<SimpleQueryNodeTypes>::create(iterator); @@ -618,6 +624,26 @@ TEST("require that All Range Syntaxes Work") { EXPECT_TRUE(range2 == range_term->getTerm()); } +TEST("require that fuzzy node can be created") { + QueryBuilder<SimpleQueryNodeTypes> builder; + builder.addFuzzyTerm("term", "view", 0, Weight(0), 3, 1); + Node::UP node = builder.build(); + + string stackDump = StackDumpCreator::create(*node); + { + SimpleQueryStackDumpIterator iterator(stackDump); + Node::UP new_node = QueryTreeCreator<SimpleQueryNodeTypes>::create(iterator); + FuzzyTerm *fuzzy_node = as_node<FuzzyTerm>(new_node.get()); + EXPECT_EQUAL(3u, fuzzy_node->getMaxEditDistance()); + EXPECT_EQUAL(1u, fuzzy_node->getPrefixLength()); + } + { + search::QueryTermSimple::UP queryTermSimple = search::QueryTermDecoder::decodeTerm(stackDump); + EXPECT_EQUAL(3u, queryTermSimple->getFuzzyMaxEditDistance()); + EXPECT_EQUAL(1u, queryTermSimple->getFuzzyPrefixLength()); + } +} + TEST("require that empty intermediate node can be added") { QueryBuilder<SimpleQueryNodeTypes> builder; builder.addAnd(0); diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index ec292eda8eb..4b5433dd370 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -805,9 +805,9 @@ TEST("testSameElementEvaluate") { } TEST("Control the size of query terms") { - EXPECT_EQUAL(104u, sizeof(QueryTermSimple)); - EXPECT_EQUAL(120u, sizeof(QueryTermUCS4)); - EXPECT_EQUAL(264u, sizeof(QueryTerm)); + EXPECT_EQUAL(112u, sizeof(QueryTermSimple)); + EXPECT_EQUAL(128u, sizeof(QueryTermUCS4)); + EXPECT_EQUAL(272u, sizeof(QueryTerm)); } TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/vespa/searchlib/attribute/string_search_helper.cpp b/searchlib/src/vespa/searchlib/attribute/string_search_helper.cpp index d876d80e73f..cd233b75438 100644 --- a/searchlib/src/vespa/searchlib/attribute/string_search_helper.cpp +++ b/searchlib/src/vespa/searchlib/attribute/string_search_helper.cpp @@ -27,7 +27,10 @@ StringSearchHelper::StringSearchHelper(QueryTermUCS4 & term, bool cased) _term._char = term.getTerm(); _termLen = term.getTermLen(); } else if (isFuzzy()) { - _fuzzyMatcher = vespalib::FuzzyMatcher::from_term(term.getTerm()); + _fuzzyMatcher = vespalib::FuzzyMatcher::from_term( + term.getTerm(), + term.getFuzzyMaxEditDistance(), + term.getFuzzyPrefixLength()); } else { term.term(_term._ucs4); } diff --git a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp index 85b55284b35..f625a2b7fd2 100644 --- a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp +++ b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp @@ -170,7 +170,6 @@ bool SimpleQueryStackDumpIterator::readNext() { case ParseItem::ITEM_EXACTSTRINGTERM: case ParseItem::ITEM_SUFFIXTERM: case ParseItem::ITEM_REGEXP: - case ParseItem::ITEM_FUZZY: _curr_index_name = read_stringref(p); _curr_term = read_stringref(p); _currArity = 0; @@ -188,6 +187,9 @@ bool SimpleQueryStackDumpIterator::readNext() { case ParseItem::ITEM_NEAREST_NEIGHBOR: if ( ! readNN(p)) return false; break; + case ParseItem::ITEM_FUZZY: + if (!readFuzzy(p)) return false; + break; case ParseItem::ITEM_TRUE: case ParseItem::ITEM_FALSE: // no content @@ -256,4 +258,14 @@ SimpleQueryStackDumpIterator::readComplexTerm(const char *& p) { return true; } +bool +SimpleQueryStackDumpIterator::readFuzzy(const char *&p) { + _curr_index_name = read_stringref(p); + _curr_term = read_stringref(p); // fuzzy term + _extraIntArg1 = readCompressedPositiveInt(p); // maxEditDistance + _extraIntArg2 = readCompressedPositiveInt(p); // prefixLength + _currArity = 0; + return true; +} + } diff --git a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h index 5cec16000b7..ca3e3f6be10 100644 --- a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h +++ b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h @@ -54,6 +54,7 @@ private: VESPA_DLL_LOCAL bool readPredicate(const char *&p); VESPA_DLL_LOCAL bool readNN(const char *&p); VESPA_DLL_LOCAL bool readComplexTerm(const char *& p); + VESPA_DLL_LOCAL bool readFuzzy(const char *&p); VESPA_DLL_LOCAL bool readNext(); public: /** @@ -115,6 +116,10 @@ public: bool getAllowApproximate() const { return (_extraIntArg2 != 0); } uint32_t getExploreAdditionalHits() const { return _extraIntArg3; } + // fuzzy match arguments + uint32_t getFuzzyMaxEditDistance() const { return _extraIntArg1; } + uint32_t getFuzzyPrefixLength() const { return _extraIntArg2; } + query::PredicateQueryTerm::UP getPredicateQueryTerm() { return std::move(_predicate_query_term); } vespalib::stringref getIndexName() const { return _curr_index_name; } diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index e0fcc8b690c..17e50216a23 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -210,7 +210,9 @@ QueryTermSimple::QueryTermSimple(const string & term_, Type type) _diversityCutoffStrict(false), _valid(true), _term(term_), - _diversityAttribute() + _diversityAttribute(), + _fuzzyMaxEditDistance(2), + _fuzzyPrefixLength(0) { if (isFullRange(_term)) { stringref rest(_term.c_str() + 1, _term.size() - 2); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.h b/searchlib/src/vespa/searchlib/query/query_term_simple.h index 0d5dd116826..b84813cd12e 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.h +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.h @@ -52,6 +52,8 @@ public: size_t getDiversityCutoffGroups() const { return _diversityCutoffGroups; } bool getDiversityCutoffStrict() const { return _diversityCutoffStrict; } vespalib::stringref getDiversityAttribute() const { return _diversityAttribute; } + size_t getFuzzyMaxEditDistance() const { return _fuzzyMaxEditDistance; } + size_t getFuzzyPrefixLength() const { return _fuzzyPrefixLength; } bool getAsIntegerTerm(int64_t & lower, int64_t & upper) const; bool getAsDoubleTerm(double & lower, double & upper) const; const char * getTerm() const { return _term.c_str(); } @@ -68,6 +70,7 @@ public: vespalib::string getClassName() const; bool isValid() const { return _valid; } const string & getTermString() const { return _term; } + private: bool getRangeInternal(int64_t & low, int64_t & high) const; template <typename N> @@ -84,6 +87,10 @@ private: stringref _diversityAttribute; template <typename T, typename D> bool getAsNumericTerm(T & lower, T & upper, D d) const; + +protected: + uint32_t _fuzzyMaxEditDistance; // set in QueryTerm + uint32_t _fuzzyPrefixLength; }; } diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index 6f126c7a3eb..6d59886a4f5 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -140,6 +140,10 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor auto qt = std::make_unique<QueryTerm>(factory.create(), ssTerm, ssIndex, sTerm); qt->setWeight(queryRep.GetWeight()); qt->setUniqueId(queryRep.getUniqueId()); + if (qt->isFuzzy()) { + qt->setFuzzyMaxEditDistance(queryRep.getFuzzyMaxEditDistance()); + qt->setFuzzyPrefixLength(queryRep.getFuzzyPrefixLength()); + } if (qt->encoding().isBase10Integer() || ! qt->encoding().isFloat() || ! factory.getRewriteFloatTerms() || diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h index 25f2b598413..34b1b87491e 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h @@ -85,6 +85,10 @@ public: void visitMembers(vespalib::ObjectVisitor &visitor) const override; void setIndex(const string & index_) override { _index = index_; } const string & getIndex() const override { return _index; } + void setFuzzyMaxEditDistance(uint32_t fuzzyMaxEditDistance) { _fuzzyMaxEditDistance = fuzzyMaxEditDistance; } + void setFuzzyPrefixLength(uint32_t fuzzyPrefixLength) { _fuzzyPrefixLength = fuzzyPrefixLength; } + uint32_t fuzzyMaxEditDistance() const { return _fuzzyMaxEditDistance; } + uint32_t fuzzyPrefixLength() const { return _fuzzyPrefixLength; } protected: using QueryNodeResultBaseContainer = std::unique_ptr<QueryNodeResultBase>; string _index; diff --git a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h index ee3a944cce1..2273dadbfcf 100644 --- a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h +++ b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h @@ -222,8 +222,9 @@ create_nearest_neighbor_term(vespalib::stringref query_tensor_name, vespalib::st } template <class NodeTypes> typename NodeTypes::FuzzyTerm * -createFuzzyTerm(vespalib::stringref term, vespalib::stringref view, int32_t id, Weight weight) { - return new typename NodeTypes::FuzzyTerm(term, view, id, weight); +createFuzzyTerm(vespalib::stringref term, vespalib::stringref view, int32_t id, Weight weight, + uint32_t maxEditDistance, uint32_t prefixLength) { + return new typename NodeTypes::FuzzyTerm(term, view, id, weight, maxEditDistance, prefixLength); } @@ -333,9 +334,10 @@ public: adjustWeight(weight); return addTerm(createRegExpTerm<NodeTypes>(term, view, id, weight)); } - typename NodeTypes::FuzzyTerm &addFuzzyTerm(stringref term, stringref view, int32_t id, Weight weight) { + typename NodeTypes::FuzzyTerm &addFuzzyTerm(stringref term, stringref view, int32_t id, Weight weight, + uint32_t maxEditDistance, uint32_t prefixLength) { adjustWeight(weight); - return addTerm(createFuzzyTerm<NodeTypes>(term, view, id, weight)); + return addTerm(createFuzzyTerm<NodeTypes>(term, view, id, weight, maxEditDistance, prefixLength)); } typename NodeTypes::NearestNeighborTerm &add_nearest_neighbor_term(stringref query_tensor_name, stringref field_name, int32_t id, Weight weight, uint32_t target_num_hits, diff --git a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h index ecaee350b21..52cfbc5effb 100644 --- a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h +++ b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h @@ -197,7 +197,8 @@ private: void visit(FuzzyTerm &node) override { replicate(node, _builder.addFuzzyTerm( node.getTerm(), node.getView(), - node.getId(), node.getWeight())); + node.getId(), node.getWeight(), + node.getMaxEditDistance(), node.getPrefixLength())); } }; diff --git a/searchlib/src/vespa/searchlib/query/tree/simplequery.h b/searchlib/src/vespa/searchlib/query/tree/simplequery.h index 00dad2597ce..05e731c0c5c 100644 --- a/searchlib/src/vespa/searchlib/query/tree/simplequery.h +++ b/searchlib/src/vespa/searchlib/query/tree/simplequery.h @@ -154,8 +154,9 @@ struct SimpleNearestNeighborTerm : NearestNeighborTerm { }; struct SimpleFuzzyTerm : FuzzyTerm { SimpleFuzzyTerm(const Type &term, vespalib::stringref view, - int32_t id, Weight weight) - : FuzzyTerm(term, view, id, weight) { + int32_t id, Weight weight, + uint32_t maxEditDistance, uint32_t prefixLength) + : FuzzyTerm(term, view, id, weight, maxEditDistance, prefixLength) { } ~SimpleFuzzyTerm() override; }; diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp index f36410d1845..5ed33ec18a1 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp @@ -280,6 +280,8 @@ class QueryNodeConverter : public QueryVisitor { void visit(FuzzyTerm &node) override { createTerm(node, ParseItem::ITEM_FUZZY); + appendCompressedPositiveNumber(node.getMaxEditDistance()); + appendCompressedPositiveNumber(node.getPrefixLength()); } void visit(NearestNeighborTerm &node) override { diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h index a5f3be3e618..4103c3b1766 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h @@ -198,7 +198,9 @@ private: } else if (type == ParseItem::ITEM_REGEXP) { t = &builder.addRegExpTerm(term, view, id, weight); } else if (type == ParseItem::ITEM_FUZZY) { - t = &builder.addFuzzyTerm(term, view, id, weight); + uint32_t maxEditDistance = queryStack.getFuzzyMaxEditDistance(); + uint32_t prefixLength = queryStack.getFuzzyPrefixLength(); + t = &builder.addFuzzyTerm(term, view, id, weight, maxEditDistance, prefixLength); } else { vespalib::Issue::report("query builder: Unable to create query tree from stack dump. node type = %d.", type); } diff --git a/searchlib/src/vespa/searchlib/query/tree/termnodes.h b/searchlib/src/vespa/searchlib/query/tree/termnodes.h index 7aa867e25ed..5604a3afb52 100644 --- a/searchlib/src/vespa/searchlib/query/tree/termnodes.h +++ b/searchlib/src/vespa/searchlib/query/tree/termnodes.h @@ -117,13 +117,21 @@ public: //----------------------------------------------------------------------------- -class FuzzyTerm : public QueryNodeMixin<FuzzyTerm, StringBase> -{ +class FuzzyTerm : public QueryNodeMixin<FuzzyTerm, StringBase> { +private: + uint32_t _maxEditDistance; + uint32_t _prefixLength; public: FuzzyTerm(const Type &term, vespalib::stringref view, - int32_t id, Weight weight) - : QueryNodeMixinType(term, view, id, weight) + int32_t id, Weight weight, uint32_t maxEditDistance, uint32_t prefixLength) + : QueryNodeMixinType(term, view, id, weight), + _maxEditDistance(maxEditDistance), + _prefixLength(prefixLength) {} + + uint32_t getMaxEditDistance() const { return _maxEditDistance; } + uint32_t getPrefixLength() const { return _prefixLength; } + virtual ~FuzzyTerm() = 0; }; |