Skip to content
Permalink
Browse files
Support allowLeadingWildcard for elastic (#424)
* Support allowLeadingWildcard for elastic
  • Loading branch information
nit0906 committed Jan 4, 2022
1 parent 35ffc63 commit ce9c91bdae8afe821b4e8092fdc2c726ec94e9d6
Showing 2 changed files with 64 additions and 4 deletions.
@@ -785,7 +785,28 @@ private static QueryBuilder fullTextQuery(String text, String fieldName, PlanRes
// and could contain other parts like renditions, node name, etc
return multiMatchQuery.field(fieldName);
} else {
return simpleQueryStringQuery(text).field(fieldName).defaultOperator(Operator.AND);
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
// simpleQueryStringQuery does not support leading wildcards whereas it's supported by default in queryStringQuery
// Not using queryStringQuery by default , since some functional cases break.
// simpleQueryStringQuery is less Strict, for instance searches for terms starting with / work, whereas
// with queryStringQuery, they throw an Exception (which ultimately results in an empty result set in oak),
// so using simpleQueryStringQuery by default would break certain functional cases.
// So only support this in case any term in the text String actually starts with *
// For example *hello or Hello *world
String[] textTerms = text.split(" ");
boolean allowLeadingWildCard = false;
for(String textTerm : textTerms) {
if (textTerm.startsWith("*")) {
allowLeadingWildCard = true;
break;
}
}

if (allowLeadingWildCard) {
return queryStringQuery(text).field(fieldName).defaultOperator(Operator.AND);
} else {
return simpleQueryStringQuery(text).analyzeWildcard(true).field(fieldName).defaultOperator(Operator.AND);
}
}
}

@@ -24,9 +24,7 @@
import org.junit.Ignore;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.*;

import static java.util.Collections.singletonList;
import static java.util.Arrays.asList;
@@ -67,6 +65,7 @@ protected void createTestIndexNode() throws Exception {
TestUtil.enableFunctionIndex(props, "length([name])");
TestUtil.enableFunctionIndex(props, "lower([name])");
TestUtil.enableFunctionIndex(props, "upper([name])");
TestUtil.enableForFullText(props, "propa", false);

root.commit();
}
@@ -459,6 +458,46 @@ public void oak3371() throws Exception {
setTraversalEnabled(true);
}


@Test
public void fullTextQueryTestAllowLeadingWildcards() throws Exception {

//add content
Tree test = root.getTree("/").addChild("test");

test.addChild("a").setProperty("propa", "ship_to_canada");
test.addChild("b").setProperty("propa", "steamship_to_canada");
test.addChild("c").setProperty("propa", "ship_to_can");
test.addChild("d").setProperty("propa", "starship");
test.addChild("e").setProperty("propa", "Hello starship");
root.commit();

String query = "//*[jcr:contains(@propa, 'Hello *ship')] ";
assertEventually(() -> {
assertQuery(query, XPATH, Arrays.asList("/test/e"));
});
}


@Test
public void fullTextQueryTestAllowLeadingWildcards2() throws Exception {

//add content
Tree test = root.getTree("/").addChild("test");

test.addChild("a").setProperty("propa", "ship_to_canada");
test.addChild("b").setProperty("propa", "steamship_to_canada");
test.addChild("c").setProperty("propa", "ship_to_can");
test.addChild("d").setProperty("propa", "starship");
test.addChild("e").setProperty("propa", "Hello starship");
root.commit();

String query = "//*[jcr:contains(@propa, '*ship to can*')] ";
assertEventually(() -> {
assertQuery(query, XPATH, Arrays.asList("/test/a", "/test/b", "/test/c"));
});
}

private static Tree child(Tree t, String n, String type) {
Tree t1 = t.addChild(n);
t1.setProperty(JCR_PRIMARYTYPE, type, Type.NAME);

0 comments on commit ce9c91b

Please sign in to comment.