You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ng...@apache.org on 2022/01/04 05:50:47 UTC

[jackrabbit-oak] branch trunk updated: Support allowLeadingWildcard for elastic (#424)

This is an automated email from the ASF dual-hosted git repository.

ngupta pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/trunk by this push:
     new ce9c91b  Support allowLeadingWildcard for elastic (#424)
ce9c91b is described below

commit ce9c91bdae8afe821b4e8092fdc2c726ec94e9d6
Author: nit0906 <ni...@gmail.com>
AuthorDate: Tue Jan 4 11:20:42 2022 +0530

    Support allowLeadingWildcard for elastic (#424)
    
    * Support allowLeadingWildcard for elastic
---
 .../index/elastic/query/ElasticRequestHandler.java | 23 ++++++++++-
 .../oak/plugins/index/IndexQueryCommonTest.java    | 45 ++++++++++++++++++++--
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java
index 24c8fac..3848ca5 100644
--- a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java
+++ b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java
@@ -785,7 +785,28 @@ public class ElasticRequestHandler {
             // 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);
+            }
         }
     }
 
diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java
index f4ce2af..42a1e06 100644
--- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java
+++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java
@@ -24,9 +24,7 @@ import org.apache.jackrabbit.oak.query.AbstractQueryTest;
 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 @@ public abstract class IndexQueryCommonTest extends AbstractQueryTest {
         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 abstract class IndexQueryCommonTest extends AbstractQueryTest {
         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);