Repository: searchbox-io/Jest
Pull request #419 (2016-11-22 14:49:50)

Support for _source filtering #413
@ferhatsb @dhayha 
here you are :)
I made it^^

concerned issue - https://github.com/searchbox-io/Jest/issues/413 


Patch:
diff --git a/jest-common/src/main/java/io/searchbox/core/Search.java b/jest-common/src/main/java/io/searchbox/core/Search.java
index f7553bbf..4afb7111 100644
--- a/jest-common/src/main/java/io/searchbox/core/Search.java
+++ b/jest-common/src/main/java/io/searchbox/core/Search.java
@@ -1,15 +1,22 @@
 package io.searchbox.core;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
 import com.google.gson.Gson;
+
 import io.searchbox.action.AbstractAction;
 import io.searchbox.action.AbstractMultiTypeActionBuilder;
 import io.searchbox.core.search.sort.Sort;
 import io.searchbox.params.Parameters;
 import io.searchbox.params.SearchType;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-
-import java.util.*;
 
 /**
  * @author Dogukan Sonmez
@@ -19,21 +26,27 @@ public class Search extends AbstractAction<SearchResult> {
 
     private String query;
     private List<Sort> sortList = new LinkedList<Sort>();
+    protected List<String> includePatternList = new ArrayList<String>();
+    protected List<String> excludePatternList = new ArrayList<String>();
 
     protected Search(Builder builder) {
         super(builder);
 
         this.query = builder.query;
         this.sortList = builder.sortList;
+        this.includePatternList = builder.includePatternList;
+        this.excludePatternList = builder.excludePatternList;
         setURI(buildURI());
     }
-    
+
     protected Search(TemplateBuilder templatedBuilder) {
         super(templatedBuilder);
 
         //reuse query as it's just the request body of the POST
         this.query = templatedBuilder.query;
         this.sortList = templatedBuilder.sortList;
+        this.includePatternList = templatedBuilder.includePatternList;
+        this.excludePatternList = templatedBuilder.excludePatternList;
         setURI(buildURI() + "/template");
     }
 
@@ -69,11 +82,15 @@ public class Search extends AbstractAction<SearchResult> {
     @Override
     public String getData(Gson gson) {
         String data;
-        if (sortList.isEmpty()) {
+        if (sortList.isEmpty() && includePatternList.isEmpty() && excludePatternList.isEmpty()) {
             data = query;
         } else {
             Map<String, Object> rootJson = gson.fromJson(query, Map.class);
 
+            if (rootJson == null) {
+                rootJson = new HashMap();
+            }
+
             List<Map<String, Object>> sortMaps = (List<Map<String, Object>>) rootJson.get("sort");
             if (sortMaps == null) {
                 sortMaps = new ArrayList<Map<String, Object>>(sortList.size());
@@ -84,6 +101,31 @@ public class Search extends AbstractAction<SearchResult> {
                 sortMaps.add(sort.toMap());
             }
 
+            Map<String, Object> sourceMaps = (Map<String, Object>) rootJson.get("_source");
+            if (sourceMaps == null) {
+                sourceMaps = new HashMap<String, Object>();
+                if (!includePatternList.isEmpty()) {
+                    sourceMaps.put("include", includePatternList);
+                }
+                if (!excludePatternList.isEmpty()) {
+                    sourceMaps.put("exclude", excludePatternList);
+                }
+                rootJson.put("_source", sourceMaps);
+            } else {
+                List<String> include = (List<String>) sourceMaps.get("include");
+                if (include != null) {
+                    include.addAll(includePatternList);
+                } else {
+                    sourceMaps.put("include", includePatternList);
+                }
+                List<String> exclude = (List<String>) sourceMaps.get("exclude");
+                if (exclude != null) {
+                    exclude.addAll(excludePatternList);
+                } else {
+                    sourceMaps.put("exclude", excludePatternList);
+                }
+            }
+
             data = gson.toJson(rootJson);
         }
         return data;
@@ -114,12 +156,16 @@ public class Search extends AbstractAction<SearchResult> {
                 .appendSuper(super.equals(obj))
                 .append(query, rhs.query)
                 .append(sortList, rhs.sortList)
+                .append(includePatternList, rhs.includePatternList)
+                .append(excludePatternList, rhs.excludePatternList)
                 .isEquals();
     }
 
     public static class Builder extends AbstractMultiTypeActionBuilder<Search, Builder> {
         protected String query;
         protected List<Sort> sortList = new LinkedList<Sort>();
+        protected List<String> includePatternList = new ArrayList<String>();
+        protected List<String> excludePatternList = new ArrayList<String>();
 
         public Builder(String query) {
             this.query = query;
@@ -134,6 +180,16 @@ public class Search extends AbstractAction<SearchResult> {
             return this;
         }
 
+        public Builder addSourceExcludePattern(String excludePattern) {
+            excludePatternList.add(excludePattern);
+            return this;
+        }
+
+        public Builder addSourceIncludePattern(String includePattern) {
+            includePatternList.add(includePattern);
+            return this;
+        }
+
         public Builder addSort(Collection<Sort> sorts) {
             sortList.addAll(sorts);
             return this;
@@ -153,7 +209,7 @@ public class Search extends AbstractAction<SearchResult> {
     }
 
     public static class TemplateBuilder extends Builder {
-    	public TemplateBuilder(String templatedQuery) {    		
+    	public TemplateBuilder(String templatedQuery) {
             super(templatedQuery);
         }
 


Test patch:
diff --git a/jest-common/src/test/java/io/searchbox/core/SearchTest.java b/jest-common/src/test/java/io/searchbox/core/SearchTest.java
index ea80cd5b..de00d845 100644
--- a/jest-common/src/test/java/io/searchbox/core/SearchTest.java
+++ b/jest-common/src/test/java/io/searchbox/core/SearchTest.java
@@ -1,14 +1,24 @@
 package io.searchbox.core;
 
-import com.google.gson.*;
-import io.searchbox.action.Action;
-import io.searchbox.core.search.sort.Sort;
-import io.searchbox.core.search.sort.Sort.Sorting;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.Arrays;
 
-import static org.junit.Assert.*;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import io.searchbox.action.Action;
+import io.searchbox.core.search.sort.Sort;
+import io.searchbox.core.search.sort.Sort.Sorting;
 
 /**
  * @author Dogukan Sonmez
@@ -67,13 +77,13 @@ public class SearchTest {
                 .build();
         assertEquals("twitter%2Csearchbox/tweet%2Cjest/_search", search.getURI());
     }
-    
+
     @Test
     public void getURIForTemplateWithoutIndexAndType() {
         Action search = new Search.TemplateBuilder("").build();
         assertEquals("_all/_search/template", search.getURI());
     }
-    
+
     @Test
     public void getURIForTemplateWithIndexAndType() {
         Action search = new Search.TemplateBuilder("").addIndex("twitter").addType("tweet").build();
@@ -86,6 +96,56 @@ public class SearchTest {
         assertTrue("Version Parameter missing", search.getURI().contains("version=true"));
     }
 
+    @Test
+    public void sourceFilteringByQueryTest() {
+        String query = "{\"sort\":[],\"_source\":{\"exclude\":[\"excludeFieldName\"],\"include\":[\"includeFieldName\"]}}";
+        Action search = new Search.Builder(query).build();
+
+        JsonParser parser = new JsonParser();
+        JsonElement parsed = parser.parse(search.getData(new Gson()).toString());
+        JsonObject obj = parsed.getAsJsonObject();
+        JsonObject source = obj.getAsJsonObject("_source");
+
+        JsonArray includePattern = source.getAsJsonArray("include");
+        assertEquals(1, includePattern.size());
+        assertEquals("includeFieldName", includePattern.get(0).getAsString());
+
+        JsonArray excludePattern = source.getAsJsonArray("exclude");
+        assertEquals(1, excludePattern.size());
+        assertEquals("excludeFieldName", excludePattern.get(0).getAsString());
+    }
+
+    @Test
+    public void sourceFilteringParamTest() {
+        String query = "{\"query\" : { \"term\" : { \"name\" : \"KangSungJeon\" } }}";
+        String includePatternItem1 = "SeolaIncludeFieldName";
+        String includePatternItem2 = "SeohooIncludeFieldName";
+        String excludePatternItem1 = "SeolaExcludeField.*";
+        String excludePatternItem2 = "SeohooExcludeField.*";
+
+        Action search = new Search.Builder(query)
+                .addSourceIncludePattern(includePatternItem1)
+                .addSourceIncludePattern(includePatternItem2)
+                .addSourceExcludePattern(excludePatternItem1)
+                .addSourceExcludePattern(excludePatternItem2)
+                .build();
+
+        JsonParser parser = new JsonParser();
+        JsonElement parsed = parser.parse(search.getData(new Gson()).toString());
+        JsonObject obj = parsed.getAsJsonObject();
+        JsonObject source = obj.getAsJsonObject("_source");
+
+        JsonArray includePattern = source.getAsJsonArray("include");
+        assertEquals(2, includePattern.size());
+        assertEquals(includePatternItem1, includePattern.get(0).getAsString());
+        assertEquals(includePatternItem2, includePattern.get(1).getAsString());
+
+        JsonArray excludePattern = source.getAsJsonArray("exclude");
+        assertEquals(2, excludePattern.size());
+        assertEquals(excludePatternItem1, excludePattern.get(0).getAsString());
+        assertEquals(excludePatternItem2, excludePattern.get(1).getAsString());
+    }
+
     @Test
     public void sortTest() {
         String query = "{\"query\" : { \"term\" : { \"name\" : \"Milano\" } }}";
diff --git a/jest/src/test/java/io/searchbox/core/SearchIntegrationTest.java b/jest/src/test/java/io/searchbox/core/SearchIntegrationTest.java
index f0f63fcd..6c866822 100644
--- a/jest/src/test/java/io/searchbox/core/SearchIntegrationTest.java
+++ b/jest/src/test/java/io/searchbox/core/SearchIntegrationTest.java
@@ -1,21 +1,22 @@
 package io.searchbox.core;
 
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.lucene.search.Explanation;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.elasticsearch.test.ESIntegTestCase;
+import org.junit.Test;
+
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
+
 import io.searchbox.client.JestResult;
 import io.searchbox.common.AbstractIntegrationTest;
 import io.searchbox.params.Parameters;
 import io.searchbox.params.SearchType;
-import org.apache.lucene.search.Explanation;
-import org.elasticsearch.action.index.IndexRequest;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.search.builder.SearchSourceBuilder;
-import org.elasticsearch.test.ESIntegTestCase;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.List;
 
 /**
  * @author Dogukan Sonmez
@@ -66,6 +67,41 @@ public class SearchIntegrationTest extends AbstractIntegrationTest {
                 "{\"user\":\"kimchy3\"}", result.getSourceAsString());
     }
 
+    @Test
+    public void searchWithSourceFilterByQuery() throws Exception {
+        assertTrue(index(INDEX, TYPE, "Jeehong1", "{\"includeFieldName\":\"SeoHoo\",\"excludeFieldName\":\"SeongJeon\"}").isCreated());
+        assertTrue(index(INDEX, TYPE, "Jeehong2",  "{\"includeFieldName\":\"Seola\",\"excludeFieldName\":\"SeongJeon\"}").isCreated());
+        refresh();
+        ensureSearchable(INDEX);
+
+        SearchResult result = client.execute(new Search.Builder("{\"sort\":[],\"_source\":{\"include\":[\"includeFieldName\"]}}")
+                                                     .addSourceExcludePattern("excludeFieldName").build());
+        assertTrue(result.getErrorMessage(), result.isSucceeded());
+
+        List<SearchResult.Hit<Object, Void>> hits = result.getHits(Object.class);
+        assertEquals(2,hits.size());
+        assertEquals("{\"includeFieldName\":\"SeoHoo\"}," +
+                     "{\"includeFieldName\":\"Seola\"}",result.getSourceAsString());
+    }
+
+    @Test
+    public void searchWithSourceFilterByParam() throws Exception {
+        assertTrue(index(INDEX, TYPE, "Happyprg1", "{\"includeFieldName\":\"SeoHoo\",\"excludeFieldName\":\"SeongJeon\"}").isCreated());
+        assertTrue(index(INDEX, TYPE, "Happyprg2",  "{\"includeFieldName\":\"Seola\",\"excludeFieldName\":\"SeongJeon\"}").isCreated());
+        refresh();
+        ensureSearchable(INDEX);
+
+        SearchResult result = client.execute(new Search.Builder("")
+                                                     .addSourceIncludePattern("includeFieldName")
+                                                     .addSourceExcludePattern("excludeFieldName").build());
+        assertTrue(result.getErrorMessage(), result.isSucceeded());
+
+        List<SearchResult.Hit<Object, Void>> hits = result.getHits(Object.class);
+        assertEquals(2,hits.size());
+        assertEquals("{\"includeFieldName\":\"SeoHoo\"}," +
+                     "{\"includeFieldName\":\"Seola\"}",result.getSourceAsString());
+    }
+
     @Test
     public void searchWithSort() throws Exception {
         assertTrue(index(INDEX, TYPE, "sws1", "{\"user\":\"kimchy1\"}").isCreated());