Skip to content

Commit

Permalink
Merge pull request #33300 from vespa-engine/bratseth/fuzzy-in-sameEle…
Browse files Browse the repository at this point in the history
…ment

Handle Fuzzy items in SameElement correctly
  • Loading branch information
bratseth authored Feb 12, 2025
2 parents 471e8fa + 70e9b34 commit 02c9b5d
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions container-search/abi-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,7 @@
"methods" : [
"public void <init>()",
"public java.lang.String getIndexName()",
"public java.lang.String getFieldName()",
"protected void encodeThis(java.nio.ByteBuffer)",
"public void setIndexName(java.lang.String)",
"protected void appendIndexString(java.lang.StringBuilder)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,6 @@ protected void encodeThis(ByteBuffer buffer) {
IntegerCompressor.putCompressedPositiveNumber(this.maxEditDistance, buffer);
IntegerCompressor.putCompressedPositiveNumber(this.prefixLength, buffer);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ protected void appendHeadingString(StringBuilder buffer) {
* <pre>
* ([itemName] [body])
* </pre>
* The body must be appended appended by this method.
* The body must be appended by this method.
*/
protected abstract void appendBodyString(StringBuilder buffer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,18 @@ public abstract class SimpleIndexedItem extends SimpleTaggableItem implements In
private String index = "";

/** The name of the index this belongs to, or "" (never null) if not specified */
public String getIndexName() {
return index;
public String getIndexName() { return index; }

/**
* The *full* name of the field searched by this,
* which is prefixed by the parent name and a dot if this is inside a SameElement,
* and the same as getIndexName otherwise.
*/
public String getFieldName() {
if (getParent() != null && getParent() instanceof SameElementItem sameElementParent)
return sameElementParent.getFieldName() + "." + getIndexName();
else
return getIndexName();
}

// encode index bytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.SameElementItem;
import com.yahoo.prelude.query.ToolBox;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
Expand Down Expand Up @@ -65,10 +66,10 @@ public boolean visit(Item item) {

/** Returns an error message if this is invalid, or null if it is valid */
private String validate(FuzzyItem item) {
String indexName = item.getIndexName();
Index index = getIndexFromUnionOfDocumentTypes(indexName);
String fieldName = item.getFieldName();
Index index = getIndexFromUnionOfDocumentTypes(fieldName);
if (!index.isAttribute() || !index.isString()) {
return item + " field is not a string attribute";
return "Fuzzy items require a string attribute field, but '" + fieldName + "' is not";
}
if (item.getPrefixLength() < 0) {
return item + " has invalid prefixLength " + item.getPrefixLength() + ": Must be >= 0";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@
* @author alexeyche
*/
public class ValidateFuzzySearcherTestCase {

ValidateFuzzySearcher searcher;

List<String> attributes;

private List<Index> indexes;
private final List<Index> indexes;

private static final String CMD_ATTRIBUTE = "attribute";
private static final String CMD_STRING = "string";
Expand Down Expand Up @@ -65,6 +66,16 @@ private String makeQuery(String attribute, String query) {
}


@Test
void testQueryInsideSameElement() {
Index index = new Index("myMap.value");
index.setAttribute(true);
index.setString(true);
String q = "select * from sources * where myMap contains sameElement(value contains fuzzy('fuzzy'))";
Result r = doSearch(searcher, q, List.of(index));
assertNull(r.hits().getError());
}

@Test
void testQueriesToAllAttributes() {
final Set<String> validAttributes = Set.of("string_single", "string_array", "string_weightedset");
Expand All @@ -75,7 +86,7 @@ void testQueriesToAllAttributes() {
if (validAttributes.contains(attribute)) {
assertNull(r.hits().getError());
} else {
assertErrMsg("FUZZY(fuzzy,2,0,false) " + attribute + ":fuzzy field is not a string attribute", r);
assertErrMsg("Fuzzy items require a string attribute field, but '" + attribute + "' is not", r);
}
}
}
Expand Down Expand Up @@ -105,14 +116,18 @@ void testInvalidQueryWrongPrefixLength() {
void testInvalidQueryWrongAttributeName() {
String q = makeQuery("wrong_name", "fuzzy");
Result r = doSearch(searcher, q);
assertErrMsg("FUZZY(fuzzy,2,0,false) wrong_name:fuzzy field is not a string attribute", r);
assertErrMsg("Fuzzy items require a string attribute field, but 'wrong_name' is not", r);
}

private static void assertErrMsg(String message, Result r) {
assertEquals(ErrorMessage.createIllegalQuery(message), r.hits().getError());
}

private Result doSearch(ValidateFuzzySearcher searcher, String yqlQuery) {
return doSearch(searcher, yqlQuery, indexes);
}

private Result doSearch(ValidateFuzzySearcher searcher, String yqlQuery, List<Index> indexes) {
QueryTree queryTree = new YqlParser(new ParserEnvironment()).parse(new Parsable().setQuery(yqlQuery));
Query query = new Query();
query.getModel().getQueryTree().setRoot(queryTree.getRoot());
Expand All @@ -123,4 +138,5 @@ private Result doSearch(ValidateFuzzySearcher searcher, String yqlQuery) {
IndexFacts indexFacts = new IndexFacts(new IndexModel(searchDefinition));
return new Execution(searcher, Execution.Context.createContextStub(indexFacts)).search(query);
}

}

0 comments on commit 02c9b5d

Please sign in to comment.