Browse Source

Java Client - Allow to set facets in binary format, closes #442.

kimchy 14 years ago
parent
commit
94c632b79b

+ 8 - 0
modules/elasticsearch/src/main/java/org/elasticsearch/client/action/search/SearchRequestBuilder.java

@@ -367,6 +367,14 @@ public class SearchRequestBuilder extends BaseRequestBuilder<SearchRequest, Sear
         return this;
     }
 
+    /**
+     * Sets a raw (xcontent) binary representation of facets to use.
+     */
+    public SearchRequestBuilder setFacets(byte[] facets) {
+        sourceBuilder().facets(facets);
+        return this;
+    }
+
     /**
      * Adds a field to be highlighted with default fragment size of 100 characters, and
      * default number of fragments of 5.

+ 18 - 0
modules/elasticsearch/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java

@@ -90,6 +90,8 @@ public class SearchSourceBuilder implements ToXContent {
 
     private List<AbstractFacetBuilder> facets;
 
+    private byte[] facetsBinary;
+
     private HighlightBuilder highlightBuilder;
 
     private TObjectFloatHashMap<String> indexBoost = null;
@@ -228,6 +230,14 @@ public class SearchSourceBuilder implements ToXContent {
         return this;
     }
 
+    /**
+     * Sets a raw (xcontent / json) facets.
+     */
+    public SearchSourceBuilder facets(byte[] facetsBinary) {
+        this.facetsBinary = facetsBinary;
+        return this;
+    }
+
     public HighlightBuilder highlighter() {
         if (highlightBuilder == null) {
             highlightBuilder = new HighlightBuilder();
@@ -463,6 +473,14 @@ public class SearchSourceBuilder implements ToXContent {
             builder.endObject();
         }
 
+        if (facetsBinary != null) {
+            if (XContentFactory.xContentType(facetsBinary) == builder.contentType()) {
+                builder.rawField("facets", facetsBinary);
+            } else {
+                builder.field("facets_binary", facetsBinary);
+            }
+        }
+
         if (highlightBuilder != null) {
             highlightBuilder.toXContent(builder, params);
         }

+ 46 - 0
modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/FacetBinaryParseElement.java

@@ -0,0 +1,46 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.search.facet;
+
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.search.internal.SearchContext;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class FacetBinaryParseElement extends FacetParseElement {
+
+    @Inject public FacetBinaryParseElement(FacetProcessors facetProcessors) {
+        super(facetProcessors);
+    }
+
+    @Override public void parse(XContentParser parser, SearchContext context) throws Exception {
+        byte[] facetSource = parser.binaryValue();
+        XContentParser fSourceParser = XContentFactory.xContent(facetSource).createParser(facetSource);
+        try {
+            fSourceParser.nextToken(); // move past the first START_OBJECT
+            super.parse(fSourceParser, context);
+        } finally {
+            fSourceParser.close();
+        }
+    }
+}

+ 1 - 1
modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/FacetParseElement.java

@@ -83,7 +83,7 @@ public class FacetParseElement implements SearchParseElement {
                         } else {
                             FacetProcessor facetProcessor = facetProcessors.processor(facetFieldName);
                             if (facetProcessor == null) {
-                                throw new SearchParseException(context, "No facet type for [" + facetFieldName + "]");
+                                throw new SearchParseException(context, "No facet type found for [" + facetFieldName + "]");
                             }
                             facet = facetProcessor.parse(topLevelFieldName, parser, context);
                         }

+ 5 - 2
modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/FacetPhase.java

@@ -44,12 +44,15 @@ public class FacetPhase implements SearchPhase {
 
     private final FacetParseElement facetParseElement;
 
-    @Inject public FacetPhase(FacetParseElement facetParseElement) {
+    private final FacetBinaryParseElement facetBinaryParseElement;
+
+    @Inject public FacetPhase(FacetParseElement facetParseElement, FacetBinaryParseElement facetBinaryParseElement) {
         this.facetParseElement = facetParseElement;
+        this.facetBinaryParseElement = facetBinaryParseElement;
     }
 
     @Override public Map<String, ? extends SearchParseElement> parseElements() {
-        return ImmutableMap.of("facets", facetParseElement);
+        return ImmutableMap.of("facets", facetParseElement, "facets_binary", facetBinaryParseElement, "facetsBinary", facetBinaryParseElement);
     }
 
     @Override public void preProcess(SearchContext context) {

+ 44 - 0
modules/test/integration/src/test/java/org/elasticsearch/test/integration/search/facet/SimpleFacetsTests.java

@@ -26,6 +26,7 @@ import org.elasticsearch.client.Client;
 import org.elasticsearch.common.joda.time.DateTimeZone;
 import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
 import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.search.facet.datehistogram.DateHistogramFacet;
 import org.elasticsearch.search.facet.filter.FilterFacet;
 import org.elasticsearch.search.facet.histogram.HistogramFacet;
@@ -73,6 +74,49 @@ public class SimpleFacetsTests extends AbstractNodesTests {
         return client("server1");
     }
 
+    @Test public void testBinaryFacet() throws Exception {
+        try {
+            client.admin().indices().prepareDelete("test").execute().actionGet();
+        } catch (Exception e) {
+            // ignore
+        }
+        client.admin().indices().prepareCreate("test").execute().actionGet();
+        client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
+
+        client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
+
+        client.prepareIndex("test", "type1").setSource(jsonBuilder().startObject()
+                .field("tag", "green")
+                .endObject()).execute().actionGet();
+        client.admin().indices().prepareFlush().setRefresh(true).execute().actionGet();
+
+        client.prepareIndex("test", "type1").setSource(jsonBuilder().startObject()
+                .field("tag", "blue")
+                .endObject()).execute().actionGet();
+
+        client.admin().indices().prepareRefresh().execute().actionGet();
+
+        SearchResponse searchResponse = client.prepareSearch()
+                .setQuery(matchAllQuery())
+                .setFacets(XContentFactory.jsonBuilder().startObject()
+                        .startObject("facet1")
+                        .startObject("terms")
+                        .field("field", "tag")
+                        .endObject()
+                        .endObject()
+                        .endObject().copiedBytes())
+                .execute().actionGet();
+
+        assertThat(searchResponse.hits().hits().length, equalTo(2));
+        TermsFacet facet = searchResponse.facets().facet("facet1");
+        assertThat(facet.name(), equalTo("facet1"));
+        assertThat(facet.entries().size(), equalTo(2));
+        assertThat(facet.entries().get(0).term(), anyOf(equalTo("green"), equalTo("blue")));
+        assertThat(facet.entries().get(0).count(), equalTo(1));
+        assertThat(facet.entries().get(1).term(), anyOf(equalTo("green"), equalTo("blue")));
+        assertThat(facet.entries().get(1).count(), equalTo(1));
+    }
+
     @Test public void testSearchFilter() throws Exception {
         try {
             client.admin().indices().prepareDelete("test").execute().actionGet();

+ 6 - 0
plugins/lang/groovy/src/main/groovy/org/elasticsearch/groovy/client/GClient.groovy

@@ -133,6 +133,12 @@ class GClient {
         SearchRequestBuilder.metaClass.filter = {Closure c ->
             delegate.setFilter(new GXContentBuilder().buildAsBytes(c, contentType))
         }
+        SearchRequestBuilder.metaClass.setFacets = {Closure c ->
+            delegate.setFilter(new GXContentBuilder().buildAsBytes(c, contentType))
+        }
+        SearchRequestBuilder.metaClass.facets = {Closure c ->
+            delegate.setFilter(new GXContentBuilder().buildAsBytes(c, contentType))
+        }
 
         MoreLikeThisRequest.metaClass.setSearchSource = {Closure c ->
             delegate.searchSource(new GXContentBuilder().buildAsBytes(c, contentType))