diff --git a/src/main/java/io/searchbox/core/Search.java b/src/main/java/io/searchbox/core/Search.java index 9925d8e67..8658cc4d1 100644 --- a/src/main/java/io/searchbox/core/Search.java +++ b/src/main/java/io/searchbox/core/Search.java @@ -3,6 +3,7 @@ import io.searchbox.AbstractAction; import io.searchbox.Action; + import org.apache.commons.lang.StringUtils; import org.elasticsearch.index.query.QueryBuilder; import org.slf4j.Logger; @@ -10,6 +11,7 @@ import java.util.Collection; import java.util.LinkedHashSet; +import java.util.List; /** * @author Dogukan Sonmez @@ -32,6 +34,22 @@ public Search(String query) { setData(query); } + public Search(QueryBuilder query, List sortList) { + this("\"query\" : " + query.toString(), sortList); + } + + public Search(String query, List sortList) { + String sorting = ""; + for(Sort s : sortList) { + if(s != sortList.get(0)) + sorting += ",\n"; + sorting += s.toString(); + } + if(sorting.length() > 0) + sorting = "\"sort\": [" + sorting + "], \n"; + setData("{\n" + sorting + query + "\n}"); + } + protected Search() { } diff --git a/src/main/java/io/searchbox/core/Sort.java b/src/main/java/io/searchbox/core/Sort.java new file mode 100644 index 000000000..2ad60259f --- /dev/null +++ b/src/main/java/io/searchbox/core/Sort.java @@ -0,0 +1,86 @@ +package io.searchbox.core; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.Gson; + +/** + * @author Riccardo Tasso + */ + +// TODO: +// * Geo Distance Sorting (Lat Lon as Properties, Lat Lon as String, Geohash, Lat Lon as Array) +// * Script Based Sorting +// * Track Scores (it should be in the Search object) + +public class Sort { + public enum Sorting { ASC, DESC } + public enum Missing { LAST, FIRST } + + private String field = null; + private Sorting direction = null; + private Object missing = null; + private Boolean unmapped = null; + + public Sort(String field) { + this.field = field; + } + + public Sort(String field, Sorting direction) { + this.field = field; + this.direction = direction; + } + + /** + * + * @param m should be a Missing object (LAST or FIRST) or a custom value (String, Integer, Double, ...) + */ + public void setMissing(Object m) { + this.missing = m; + } + + public void setIgnoreUnmapped() { + this.unmapped = true; + } + + public String toString() { + // simple case + if(direction == null && missing == null && unmapped == null) + return "\"" + this.field + "\""; + + // build of complex cases + + Gson gson = new Gson(); // Gson will help + + Map obj = new HashMap(); + + if(direction != null) { + String dir = "asc"; + if(direction == Sorting.DESC) + dir = "desc"; + obj.put("order", dir); + } + + if(missing != null) { + Object miss = null; + if(this.missing instanceof Missing) { + Missing current = (Missing) this.missing; + if(current == Missing.LAST) miss = "_last"; + else miss = "_first"; + } else { + miss = this.missing; + } + obj.put("missing", miss); + } + + if(unmapped != null) { + obj.put("ignore_unmapped", unmapped); + } + + String json = gson.toJson(obj); + + return "{ \"" + this.field + "\" : " + json + "}"; + } + +} \ No newline at end of file diff --git a/src/test/java/io/searchbox/core/SearchTest.java b/src/test/java/io/searchbox/core/SearchTest.java index 58f6fa847..e1b686bc5 100644 --- a/src/test/java/io/searchbox/core/SearchTest.java +++ b/src/test/java/io/searchbox/core/SearchTest.java @@ -2,6 +2,13 @@ import org.junit.Test; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import io.searchbox.core.Sort.Sorting; + import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -10,6 +17,7 @@ /** * @author Dogukan Sonmez + * @author Riccardo Tasso */ @@ -215,6 +223,43 @@ public void createQueryString() { set.add("searchbox"); assertEquals("twitter,searchbox",search.createQueryString(set)); } + + @Test + public void sortTest() { + + String query = "\"query\" : { \"term\" : { \"name\" : \"Milano\" } }"; + List sorting = new ArrayList(); + sorting.add(new Sort("population", Sorting.ASC)); + sorting.add(new Sort("population", Sorting.DESC)); + sorting.add(new Sort("population")); + Search search = new Search(query, sorting); + + JsonParser parser = new JsonParser(); + JsonElement parsed = parser.parse(search.getData().toString()); + JsonObject obj = parsed.getAsJsonObject(); + JsonArray sort = obj.getAsJsonArray("sort"); + + assertEquals(3, sort.size()); + + // sort 0 + JsonObject test = sort.get(0).getAsJsonObject(); + assertTrue(test.has("population")); + + test = test.getAsJsonObject("population"); + assertTrue(test.has("order")); + assertEquals("asc", test.get("order").getAsString()); + + // sort 1 + test = sort.get(1).getAsJsonObject(); + assertTrue(test.has("population")); + + test = test.getAsJsonObject("population"); + assertTrue(test.has("order")); + assertEquals("desc", test.get("order").getAsString()); + + // sort 2 + assertEquals("population", sort.get(2).getAsString()); + } } diff --git a/src/test/java/io/searchbox/core/SortTest.java b/src/test/java/io/searchbox/core/SortTest.java new file mode 100644 index 000000000..6f6db882e --- /dev/null +++ b/src/test/java/io/searchbox/core/SortTest.java @@ -0,0 +1,155 @@ +package io.searchbox.core; + +import io.searchbox.core.Sort.Missing; +import io.searchbox.core.Sort.Sorting; + +import org.junit.Test; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import static junit.framework.Assert.*; + +/** + * @author Riccardo Tasso + */ + + +public class SortTest { + + @Test + public void simpleTest() { + Sort s = new Sort("my_field"); + assertEquals("\"my_field\"", s.toString()); + } + + @Test + public void complexTest() { + Sort s = new Sort("my_field", Sort.Sorting.ASC); + + JsonParser parser = new JsonParser(); + JsonElement parsed = parser.parse(s.toString()); + + assertTrue(parsed.getAsJsonObject().has("my_field")); + JsonElement element = parsed.getAsJsonObject().get("my_field"); + + assertTrue(element.getAsJsonObject().has("order")); + element = element.getAsJsonObject().get("order"); + assertEquals("asc", element.getAsString()); + + s = new Sort("my_field", Sort.Sorting.DESC); + + parsed = parser.parse(s.toString()); + + assertTrue(parsed.getAsJsonObject().has("my_field")); + element = parsed.getAsJsonObject().get("my_field"); + + assertTrue(element.getAsJsonObject().has("order")); + element = element.getAsJsonObject().get("order"); + assertEquals("desc", element.getAsString()); + } + + @Test + public void missingValueTest() { + + // first + + Sort s = new Sort("my_field"); + s.setMissing(Missing.FIRST); + + JsonParser parser = new JsonParser(); + JsonElement parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + JsonObject myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("missing")); + assertEquals(myField.get("missing").getAsString(), "_first"); + + // last + + s = new Sort("my_field"); + s.setMissing(Missing.LAST); + + parser = new JsonParser(); + parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("missing")); + assertEquals(myField.get("missing").getAsString(), "_last"); + + // value String + + s = new Sort("my_field"); + s.setMissing("***"); + + parser = new JsonParser(); + parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("missing")); + assertEquals(myField.get("missing").getAsString(), "***"); + + // value Integer + + s = new Sort("my_field"); + s.setMissing(new Integer(-1)); + + parser = new JsonParser(); + parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("missing")); + assertEquals(myField.get("missing").getAsInt(), -1); + + // mixed + s = new Sort("my_field", Sorting.DESC); + s.setMissing(new Integer(-1)); + + parser = new JsonParser(); + parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("missing")); + assertEquals(myField.get("missing").getAsInt(), -1); + assertTrue(myField.has("order")); + assertEquals(myField.get("order").getAsString(), "desc"); + + } + + @Test + public void unmappedTest() { + + // simple + + Sort s = new Sort("my_field"); + s.setIgnoreUnmapped(); + + JsonParser parser = new JsonParser(); + JsonElement parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + JsonObject myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("ignore_unmapped")); + assertTrue(myField.get("ignore_unmapped").getAsBoolean()); + + // complex + + s = new Sort("my_field", Sorting.DESC); + s.setMissing(Missing.LAST); + s.setIgnoreUnmapped(); + + parser = new JsonParser(); + parsed = parser.parse(s.toString()); + assertTrue(parsed.getAsJsonObject().has("my_field")); + + myField = parsed.getAsJsonObject().get("my_field").getAsJsonObject(); + assertTrue(myField.has("ignore_unmapped")); + assertTrue(myField.get("ignore_unmapped").getAsBoolean()); + } + +}