Repository: searchbox-io/Jest
Pull request #578 (2018-02-05 19:48:57)

Adding matched_queries to search hits
Queries/sub-queries that match named queries are returned as `matched_queries` in the Elasticsearch response. Matched queries aren't currently populated in `SearchHit`s. This PR adds a new field to `SearchHit` and populates the new field.

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-named-queries-and-filters.html


Patch:
diff --git a/jest-common/src/main/java/io/searchbox/core/SearchResult.java b/jest-common/src/main/java/io/searchbox/core/SearchResult.java
index 6fa21ab5..ff8bc8a8 100644
--- a/jest-common/src/main/java/io/searchbox/core/SearchResult.java
+++ b/jest-common/src/main/java/io/searchbox/core/SearchResult.java
@@ -132,6 +132,14 @@ public class SearchResult extends JestResult {
                 Map<String, List<String>> highlight = extractHighlight(hitObject.getAsJsonObject(HIGHLIGHT_KEY));
                 List<String> sort = extractSort(hitObject.getAsJsonArray(SORT_KEY));
 
+                List<String> matchedQueries = new ArrayList<>();
+                if (hitObject.has("matched_queries") && !hitObject.get("matched_queries").isJsonNull()) {
+                    JsonArray rawMatchedQueries = hitObject.get("matched_queries").getAsJsonArray();
+                    rawMatchedQueries.forEach(matchedQuery -> {
+                        matchedQueries.add(matchedQuery.getAsString());
+                    });
+                }
+
                 if (addEsMetadataFields) {
                     JsonObject clonedSource = null;
                     for (MetaField metaField : META_FIELDS) {
@@ -160,7 +168,8 @@ public class SearchResult extends JestResult {
                         id,
                         score,
                         parent,
-                        routing
+                        routing,
+                        matchedQueries
                 );
             }
         }
@@ -255,10 +264,7 @@ public class SearchResult extends JestResult {
         public final Double score;
         public final String parent;
         public final String routing;
-
-        public Hit(Class<T> sourceType, JsonElement source) {
-            this(sourceType, source, null, null);
-        }
+        public final List<String> matchedQueries;
 
         public Hit(Class<T> sourceType, JsonElement source, Class<K> explanationType, JsonElement explanation) {
             this(sourceType, source, explanationType, explanation, null, null);
@@ -266,11 +272,12 @@ public class SearchResult extends JestResult {
 
         public Hit(Class<T> sourceType, JsonElement source, Class<K> explanationType, JsonElement explanation,
                    Map<String, List<String>> highlight, List<String> sort) {
-            this(sourceType, source, explanationType, explanation, highlight, sort, null, null, null, null);
+            this(sourceType, source, explanationType, explanation, highlight, sort, null, null, null, null, null, null, null);
         }
 
         public Hit(Class<T> sourceType, JsonElement source, Class<K> explanationType, JsonElement explanation,
-                   Map<String, List<String>> highlight, List<String> sort, String index, String type, String id, Double score, String parent, String routing) {
+                   Map<String, List<String>> highlight, List<String> sort, String index, String type, String id,
+                   Double score, String parent, String routing, List<String> matchedQueries) {
             if (source == null) {
                 this.source = null;
             } else {
@@ -288,14 +295,14 @@ public class SearchResult extends JestResult {
             this.type = type;
             this.id = id;
             this.score = score;
-            
             this.parent = parent;
             this.routing = routing;
+            this.matchedQueries = matchedQueries;
         }
         
         public Hit(Class<T> sourceType, JsonElement source, Class<K> explanationType, JsonElement explanation,
                 Map<String, List<String>> highlight, List<String> sort, String index, String type, String id, Double score) {
-            this(sourceType, source, explanationType, explanation, highlight, sort, index, type, id, score, null, null);
+            this(sourceType, source, explanationType, explanation, highlight, sort, index, type, id, score, null, null, null);
         }
 
         public Hit(T source) {
@@ -307,22 +314,21 @@ public class SearchResult extends JestResult {
         }
 
         public Hit(T source, K explanation, Map<String, List<String>> highlight, List<String> sort) {
-            this(source, explanation, highlight, sort, null, null, null, null);
+            this(source, explanation, highlight, sort, null, null, null, null, null);
         }
 
-        public Hit(T source, K explanation, Map<String, List<String>> highlight, List<String> sort, String index, String type, String id, Double score) {
+        public Hit(T source, K explanation, Map<String, List<String>> highlight, List<String> sort, String index, String type, String id, Double score, List<String> matchedQueries) {
             this.source = source;
             this.explanation = explanation;
             this.highlight = highlight;
             this.sort = sort;
-
             this.index = index;
             this.type = type;
             this.id = id;
             this.score = score;
-            
             this.parent = null;
             this.routing = null;
+            this.matchedQueries = matchedQueries;
         }
 
         @Override


Test patch:
diff --git a/jest-common/src/test/java/io/searchbox/core/SearchResultTest.java b/jest-common/src/test/java/io/searchbox/core/SearchResultTest.java
index 0cff9d6f..5c5527a9 100644
--- a/jest-common/src/test/java/io/searchbox/core/SearchResultTest.java
+++ b/jest-common/src/test/java/io/searchbox/core/SearchResultTest.java
@@ -6,6 +6,7 @@ import io.searchbox.annotations.JestId;
 import io.searchbox.annotations.JestVersion;
 import org.junit.Test;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -229,6 +230,7 @@ public class SearchResultTest {
         assertNotNull(hit.sort);
         assertNotNull(hit.id);
         assertNull(hit.score);
+        assertEquals(Collections.emptyList(), hit.matchedQueries);
 
         hit = searchResult.getFirstHit(Object.class, Object.class);
         assertNotNull(hit);
@@ -237,6 +239,7 @@ public class SearchResultTest {
         assertNotNull(hit.sort);
         assertNotNull(hit.id);
         assertNull(hit.score);
+        assertEquals(Collections.emptyList(), hit.matchedQueries);
     }
 
     @Test
@@ -417,6 +420,61 @@ public class SearchResultTest {
         assertEquals("Incorrect version", someVersion, hit.source.getVersion());
     }  
 
+    @Test
+    public void testGetMatchedQueries() {
+        String jsonWithScore = "{\n" +
+                "    \"_shards\":{\n" +
+                "        \"total\" : 5,\n" +
+                "        \"successful\" : 5,\n" +
+                "        \"failed\" : 0\n" +
+                "    },\n" +
+                "    \"hits\":{\n" +
+                "        \"total\" : 1,\n" +
+                "        \"hits\" : [\n" +
+                "            {\n" +
+                "                \"_index\" : \"twitter\",\n" +
+                "                \"_type\" : \"tweet\",\n" +
+                "                \"_score\" : \"1.02332\",\n" +
+                "                \"_id\" : \"1\",\n" +
+                "                \"_source\" : {\n" +
+                "                    \"user\" : \"kimchy\",\n" +
+                "                    \"postDate\" : \"2009-11-15T14:12:12\",\n" +
+                "                    \"message\" : \"trying out Elasticsearch\"\n" +
+                "                },\n" +
+                "                \"sort\" : [\n" +
+                "                     1234.5678\n" +
+                "                ], \n" +
+                "                \"matched_queries\" : [\"some-query\"] \n" +
+                "            }\n" +
+                "        ]\n" +
+                "    }\n" +
+                "}";
+
+        SearchResult searchResult = new SearchResult(new Gson());
+        searchResult.setSucceeded(true);
+        searchResult.setJsonString(jsonWithScore);
+        searchResult.setJsonObject(new JsonParser().parse(jsonWithScore).getAsJsonObject());
+        searchResult.setPathToResult("hits/hits/_source");
+
+        SearchResult.Hit hit = searchResult.getFirstHit(Object.class);
+        assertNotNull(hit);
+        assertNotNull(hit.source);
+        assertNull(hit.explanation);
+        assertNotNull(hit.sort);
+        assertNotNull(hit.id);
+        assertNotNull(hit.score);
+        assertEquals("Incorrect Matched Query", Collections.singletonList("some-query"), hit.matchedQueries);
+
+        hit = searchResult.getFirstHit(Object.class, Object.class);
+        assertNotNull(hit);
+        assertNotNull(hit.source);
+        assertNull(hit.explanation);
+        assertNotNull(hit.sort);
+        assertNotNull(hit.id);
+        assertNotNull(hit.score);
+        assertEquals("Incorrect Matched Query", Collections.singletonList("some-query"), hit.matchedQueries);
+    }
+
     class TestObject {
         @JestId
         private String id;