|  | @@ -40,7 +40,6 @@ import java.util.List;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.index.query.QueryBuilders.termQuery;
 | 
	
		
			
				|  |  | -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.search.aggregations.AggregationBuilders.avg;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.search.aggregations.AggregationBuilders.filters;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.search.aggregations.AggregationBuilders.histogram;
 | 
	
	
		
			
				|  | @@ -55,7 +54,7 @@ import static org.hamcrest.core.IsNull.notNullValue;
 | 
	
		
			
				|  |  |  @ElasticsearchIntegrationTest.SuiteScopeTest
 | 
	
		
			
				|  |  |  public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    static int numDocs, numTag1Docs, numTag2Docs;
 | 
	
		
			
				|  |  | +    static int numDocs, numTag1Docs, numTag2Docs, numOtherDocs;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public void setupSuiteScopeCluster() throws Exception {
 | 
	
	
		
			
				|  | @@ -63,6 +62,7 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |          createIndex("idx2");
 | 
	
		
			
				|  |  |          numDocs = randomIntBetween(5, 20);
 | 
	
		
			
				|  |  |          numTag1Docs = randomIntBetween(1, numDocs - 1);
 | 
	
		
			
				|  |  | +        numTag2Docs = randomIntBetween(1, numDocs - numTag1Docs);
 | 
	
		
			
				|  |  |          List<IndexRequestBuilder> builders = new ArrayList<>();
 | 
	
		
			
				|  |  |          for (int i = 0; i < numTag1Docs; i++) {
 | 
	
		
			
				|  |  |              XContentBuilder source = jsonBuilder()
 | 
	
	
		
			
				|  | @@ -76,8 +76,7 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |                  builders.add(client().prepareIndex("idx", "type", ""+i).setSource(source));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        for (int i = numTag1Docs; i < numDocs; i++) {
 | 
	
		
			
				|  |  | -            numTag2Docs++;
 | 
	
		
			
				|  |  | +        for (int i = numTag1Docs; i < (numTag1Docs + numTag2Docs); i++) {
 | 
	
		
			
				|  |  |              XContentBuilder source = jsonBuilder()
 | 
	
		
			
				|  |  |                      .startObject()
 | 
	
		
			
				|  |  |                      .field("value", i)
 | 
	
	
		
			
				|  | @@ -89,6 +88,15 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |                  builders.add(client().prepareIndex("idx", "type", ""+i).setSource(source));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        for (int i = numTag1Docs + numTag2Docs; i < numDocs; i++) {
 | 
	
		
			
				|  |  | +            numOtherDocs++;
 | 
	
		
			
				|  |  | +            XContentBuilder source = jsonBuilder().startObject().field("value", i).field("tag", "tag3").field("name", "name" + i)
 | 
	
		
			
				|  |  | +                    .endObject();
 | 
	
		
			
				|  |  | +            builders.add(client().prepareIndex("idx", "type", "" + i).setSource(source));
 | 
	
		
			
				|  |  | +            if (randomBoolean()) {
 | 
	
		
			
				|  |  | +                builders.add(client().prepareIndex("idx", "type", "" + i).setSource(source));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          prepareCreate("empty_bucket_idx").addMapping("type", "value", "type=integer").execute().actionGet();
 | 
	
		
			
				|  |  |          for (int i = 0; i < 2; i++) {
 | 
	
		
			
				|  |  |              builders.add(client().prepareIndex("empty_bucket_idx", "type", ""+i).setSource(jsonBuilder()
 | 
	
	
		
			
				|  | @@ -188,7 +196,7 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |          assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  |          assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  |          sum = 0;
 | 
	
		
			
				|  |  | -        for (int i = numTag1Docs; i < numDocs; ++i) {
 | 
	
		
			
				|  |  | +        for (int i = numTag1Docs; i < (numTag1Docs + numTag2Docs); ++i) {
 | 
	
		
			
				|  |  |              sum += i;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          assertThat(bucket.getAggregations().asList().isEmpty(), is(false));
 | 
	
	
		
			
				|  | @@ -242,7 +250,7 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |          assertThat(all.getKeyAsString(), equalTo("all"));
 | 
	
		
			
				|  |  |          assertThat(all.getDocCount(), is(0l));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @Test
 | 
	
		
			
				|  |  |      public void simple_nonKeyed() throws Exception {
 | 
	
		
			
				|  |  |          SearchResponse response = client().prepareSearch("idx")
 | 
	
	
		
			
				|  | @@ -272,4 +280,169 @@ public class FiltersTests extends ElasticsearchIntegrationTest {
 | 
	
		
			
				|  |  |          assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Test
 | 
	
		
			
				|  |  | +    public void otherBucket() throws Exception {
 | 
	
		
			
				|  |  | +        SearchResponse response = client()
 | 
	
		
			
				|  |  | +                .prepareSearch("idx")
 | 
	
		
			
				|  |  | +                .addAggregation(
 | 
	
		
			
				|  |  | +                        filters("tags").otherBucket(true)
 | 
	
		
			
				|  |  | +                        .filter("tag1", termQuery("tag", "tag1"))
 | 
	
		
			
				|  |  | +                        .filter("tag2", termQuery("tag", "tag2")))
 | 
	
		
			
				|  |  | +                .execute().actionGet();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertSearchResponse(response);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters filters = response.getAggregations().get("tags");
 | 
	
		
			
				|  |  | +        assertThat(filters, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(filters.getName(), equalTo("tags"));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(filters.getBuckets().size(), equalTo(3));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters.Bucket bucket = filters.getBucketByKey("tag1");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag1Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("tag2");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("_other_");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numOtherDocs));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Test
 | 
	
		
			
				|  |  | +    public void otherNamedBucket() throws Exception {
 | 
	
		
			
				|  |  | +        SearchResponse response = client()
 | 
	
		
			
				|  |  | +                .prepareSearch("idx")
 | 
	
		
			
				|  |  | +                .addAggregation(
 | 
	
		
			
				|  |  | +                        filters("tags").otherBucketKey("foobar")
 | 
	
		
			
				|  |  | +                        .filter("tag1", termQuery("tag", "tag1"))
 | 
	
		
			
				|  |  | +                        .filter("tag2", termQuery("tag", "tag2")))
 | 
	
		
			
				|  |  | +                .execute().actionGet();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertSearchResponse(response);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters filters = response.getAggregations().get("tags");
 | 
	
		
			
				|  |  | +        assertThat(filters, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(filters.getName(), equalTo("tags"));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(filters.getBuckets().size(), equalTo(3));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters.Bucket bucket = filters.getBucketByKey("tag1");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag1Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("tag2");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("foobar");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numOtherDocs));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Test
 | 
	
		
			
				|  |  | +    public void other_nonKeyed() throws Exception {
 | 
	
		
			
				|  |  | +        SearchResponse response = client().prepareSearch("idx")
 | 
	
		
			
				|  |  | +                .addAggregation(
 | 
	
		
			
				|  |  | +                        filters("tags").otherBucket(true)
 | 
	
		
			
				|  |  | +                                .filter(termQuery("tag", "tag1"))
 | 
	
		
			
				|  |  | +                                .filter(termQuery("tag", "tag2")))
 | 
	
		
			
				|  |  | +                .execute().actionGet();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertSearchResponse(response);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters filters = response.getAggregations().get("tags");
 | 
	
		
			
				|  |  | +        assertThat(filters, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(filters.getName(), equalTo("tags"));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(filters.getBuckets().size(), equalTo(3));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Collection<? extends Filters.Bucket> buckets = filters.getBuckets();
 | 
	
		
			
				|  |  | +        Iterator<? extends Filters.Bucket> itr = buckets.iterator();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters.Bucket bucket = itr.next();
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag1Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = itr.next();
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = itr.next();
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numOtherDocs));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Test
 | 
	
		
			
				|  |  | +    public void otherWithSubAggregation() throws Exception {
 | 
	
		
			
				|  |  | +        SearchResponse response = client().prepareSearch("idx")
 | 
	
		
			
				|  |  | +                .addAggregation(
 | 
	
		
			
				|  |  | +                        filters("tags").otherBucket(true)
 | 
	
		
			
				|  |  | +                                .filter("tag1", termQuery("tag", "tag1"))
 | 
	
		
			
				|  |  | +                                .filter("tag2", termQuery("tag", "tag2"))
 | 
	
		
			
				|  |  | +                                .subAggregation(avg("avg_value").field("value")))
 | 
	
		
			
				|  |  | +                .execute().actionGet();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertSearchResponse(response);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters filters = response.getAggregations().get("tags");
 | 
	
		
			
				|  |  | +        assertThat(filters, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(filters.getName(), equalTo("tags"));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(filters.getBuckets().size(), equalTo(3));
 | 
	
		
			
				|  |  | +        Object[] propertiesKeys = (Object[]) filters.getProperty("_key");
 | 
	
		
			
				|  |  | +        Object[] propertiesDocCounts = (Object[]) filters.getProperty("_count");
 | 
	
		
			
				|  |  | +        Object[] propertiesCounts = (Object[]) filters.getProperty("avg_value.value");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Filters.Bucket bucket = filters.getBucketByKey("tag1");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag1Docs));
 | 
	
		
			
				|  |  | +        long sum = 0;
 | 
	
		
			
				|  |  | +        for (int i = 0; i < numTag1Docs; ++i) {
 | 
	
		
			
				|  |  | +            sum += i + 1;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        assertThat(bucket.getAggregations().asList().isEmpty(), is(false));
 | 
	
		
			
				|  |  | +        Avg avgValue = bucket.getAggregations().get("avg_value");
 | 
	
		
			
				|  |  | +        assertThat(avgValue, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getName(), equalTo("avg_value"));
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getValue(), equalTo((double) sum / numTag1Docs));
 | 
	
		
			
				|  |  | +        assertThat((String) propertiesKeys[0], equalTo("tag1"));
 | 
	
		
			
				|  |  | +        assertThat((long) propertiesDocCounts[0], equalTo((long) numTag1Docs));
 | 
	
		
			
				|  |  | +        assertThat((double) propertiesCounts[0], equalTo((double) sum / numTag1Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("tag2");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  | +        sum = 0;
 | 
	
		
			
				|  |  | +        for (int i = numTag1Docs; i < (numTag1Docs + numTag2Docs); ++i) {
 | 
	
		
			
				|  |  | +            sum += i;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        assertThat(bucket.getAggregations().asList().isEmpty(), is(false));
 | 
	
		
			
				|  |  | +        avgValue = bucket.getAggregations().get("avg_value");
 | 
	
		
			
				|  |  | +        assertThat(avgValue, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getName(), equalTo("avg_value"));
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getValue(), equalTo((double) sum / numTag2Docs));
 | 
	
		
			
				|  |  | +        assertThat((String) propertiesKeys[1], equalTo("tag2"));
 | 
	
		
			
				|  |  | +        assertThat((long) propertiesDocCounts[1], equalTo((long) numTag2Docs));
 | 
	
		
			
				|  |  | +        assertThat((double) propertiesCounts[1], equalTo((double) sum / numTag2Docs));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bucket = filters.getBucketByKey("_other_");
 | 
	
		
			
				|  |  | +        assertThat(bucket, Matchers.notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(bucket.getDocCount(), equalTo((long) numOtherDocs));
 | 
	
		
			
				|  |  | +        sum = 0;
 | 
	
		
			
				|  |  | +        for (int i = numTag1Docs + numTag2Docs; i < numDocs; ++i) {
 | 
	
		
			
				|  |  | +            sum += i;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        assertThat(bucket.getAggregations().asList().isEmpty(), is(false));
 | 
	
		
			
				|  |  | +        avgValue = bucket.getAggregations().get("avg_value");
 | 
	
		
			
				|  |  | +        assertThat(avgValue, notNullValue());
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getName(), equalTo("avg_value"));
 | 
	
		
			
				|  |  | +        assertThat(avgValue.getValue(), equalTo((double) sum / numOtherDocs));
 | 
	
		
			
				|  |  | +        assertThat((String) propertiesKeys[2], equalTo("_other_"));
 | 
	
		
			
				|  |  | +        assertThat((long) propertiesDocCounts[2], equalTo((long) numOtherDocs));
 | 
	
		
			
				|  |  | +        assertThat((double) propertiesCounts[2], equalTo((double) sum / numOtherDocs));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |