DATAES-21 statistical facets(Petar Tahchiev)

This commit is contained in:
Artur Konczak 2013-10-11 23:24:55 +01:00
parent 99940f47c3
commit 35cb4e6930
6 changed files with 187 additions and 14 deletions

View File

@ -1,18 +1,18 @@
package org.springframework.data.elasticsearch.core.facet; package org.springframework.data.elasticsearch.core.facet;
import org.elasticsearch.search.facet.Facet; import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.histogram.HistogramFacet;
import org.elasticsearch.search.facet.range.RangeFacet; import org.elasticsearch.search.facet.range.RangeFacet;
import org.elasticsearch.search.facet.statistical.StatisticalFacet;
import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.TermsFacet;
import org.springframework.data.elasticsearch.core.facet.result.Range; import org.springframework.data.elasticsearch.core.facet.result.*;
import org.springframework.data.elasticsearch.core.facet.result.RangeResult;
import org.springframework.data.elasticsearch.core.facet.result.Term;
import org.springframework.data.elasticsearch.core.facet.result.TermResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* @author Artur Konczak * @author Artur Konczak
* @author Petar Tahchiev
*/ */
public class FacetMapper { public class FacetMapper {
@ -25,6 +25,10 @@ public class FacetMapper {
return parseRange((RangeFacet) facet); return parseRange((RangeFacet) facet);
} }
if (facet instanceof StatisticalFacet) {
return parseStatistical((StatisticalFacet) facet);
}
return null; return null;
} }
@ -44,4 +48,8 @@ public class FacetMapper {
return new RangeResult(facet.getName(), entries); return new RangeResult(facet.getName(), entries);
} }
private static FacetResult parseStatistical(StatisticalFacet facet) {
return new StatisticalResult(facet.getName(), facet.getCount(), facet.getMax(), facet.getMin(), facet.getMean(), facet.getStdDeviation(), facet.getSumOfSquares(), facet.getTotal(), facet.getVariance());
}
} }

View File

@ -1,7 +1,11 @@
package org.springframework.data.elasticsearch.core.facet; package org.springframework.data.elasticsearch.core.facet;
/**
* @author Artur Konczak
* @author Petar Tahchiev
*/
public enum FacetType { public enum FacetType {
term, range, histogram term, range, histogram, statistical
} }

View File

@ -0,0 +1,45 @@
package org.springframework.data.elasticsearch.core.facet.request;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.facet.FacetBuilders;
import org.elasticsearch.search.facet.statistical.StatisticalFacetBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
/**
* @author Petar Tahchiev
*/
public class StatisticalFacetRequest extends AbstractFacetRequest {
private String field;
private String[] fields;
public StatisticalFacetRequest(String name) {
super(name);
}
public void setField(String field) {
this.field = field;
}
public void setFields(String... fields) {
this.fields = fields;
}
public FacetBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
Assert.isTrue(StringUtils.isNotBlank(field) && fields == null, "Please select field or fields on which to build the facets !!!");
StatisticalFacetBuilder builder = FacetBuilders.statisticalFacet(getName());
if (ArrayUtils.isNotEmpty(fields)) {
builder.fields(fields);
} else {
builder.field(field);
}
return builder;
}
}

View File

@ -0,0 +1,34 @@
package org.springframework.data.elasticsearch.core.facet.request;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* @author Petar Tahchiev
*/
public class StatisticalFacetRequestBuilder {
StatisticalFacetRequest result;
public StatisticalFacetRequestBuilder(String name) {
result = new StatisticalFacetRequest(name);
}
public StatisticalFacetRequestBuilder field(String field) {
result.setField(field);
return this;
}
public StatisticalFacetRequestBuilder fields(String... fields) {
result.setFields(fields);
return this;
}
public StatisticalFacetRequestBuilder applyQueryFilter() {
result.setApplyQueryFilter(true);
return this;
}
public FacetRequest build() {
return result;
}
}

View File

@ -0,0 +1,70 @@
package org.springframework.data.elasticsearch.core.facet.result;
import org.springframework.data.elasticsearch.core.facet.AbstactFacetResult;
import org.springframework.data.elasticsearch.core.facet.FacetType;
/**
* @author Petar Tahchiev
*/
public class StatisticalResult extends AbstactFacetResult {
private long count;
private double max;
private double min;
private double mean;
private double stdDeviation;
private double sumOfSquares;
private double total;
private double variance;
public StatisticalResult(String name, long count, double max, double min, double mean, double stdDeviation, double sumOfSquares, double total, double variance) {
super(name, FacetType.statistical);
this.count = count;
this.max = max;
this.min = min;
this.mean = mean;
this.stdDeviation = stdDeviation;
this.sumOfSquares = sumOfSquares;
this.total = total;
this.variance = variance;
}
public long getCount() {
return count;
}
public double getMax() {
return max;
}
public double getMin() {
return min;
}
public double getMean() {
return mean;
}
public double getStdDeviation() {
return stdDeviation;
}
public double getSumOfSquares() {
return sumOfSquares;
}
public double getTotal() {
return total;
}
public double getVariance() {
return variance;
}
}

View File

@ -23,13 +23,8 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.FacetedPage; import org.springframework.data.elasticsearch.core.FacetedPage;
import org.springframework.data.elasticsearch.core.facet.request.NativeFacetRequest; import org.springframework.data.elasticsearch.core.facet.request.*;
import org.springframework.data.elasticsearch.core.facet.request.RangeFacetRequestBuilder; import org.springframework.data.elasticsearch.core.facet.result.*;
import org.springframework.data.elasticsearch.core.facet.request.TermFacetRequestBuilder;
import org.springframework.data.elasticsearch.core.facet.result.Range;
import org.springframework.data.elasticsearch.core.facet.result.RangeResult;
import org.springframework.data.elasticsearch.core.facet.result.Term;
import org.springframework.data.elasticsearch.core.facet.result.TermResult;
import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.data.elasticsearch.core.query.SearchQuery;
@ -57,6 +52,7 @@ public class ElasticsearchTemplateFacetTests {
public static final int YEAR_2002 = 2002; public static final int YEAR_2002 = 2002;
public static final int YEAR_2001 = 2001; public static final int YEAR_2001 = 2001;
public static final int YEAR_2000 = 2000; public static final int YEAR_2000 = 2000;
public static final String PUBLISHED_YEARS = "publishedYears";
@Autowired @Autowired
private ElasticsearchTemplate elasticsearchTemplate; private ElasticsearchTemplate elasticsearchTemplate;
@ -419,7 +415,7 @@ public class ElasticsearchTemplateFacetTests {
String facetName = "rangeYears"; String facetName = "rangeYears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet( .withFacet(
new RangeFacetRequestBuilder(facetName).field("publishedYears") new RangeFacetRequestBuilder(facetName).field(PUBLISHED_YEARS)
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build() .to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
).build(); ).build();
// when // when
@ -456,7 +452,7 @@ public class ElasticsearchTemplateFacetTests {
String facetName = "rangeScoreOverYears"; String facetName = "rangeScoreOverYears";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet( .withFacet(
new RangeFacetRequestBuilder(facetName).fields("publishedYears", "score") new RangeFacetRequestBuilder(facetName).fields(PUBLISHED_YEARS, "score")
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build() .to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
).build(); ).build();
// when // when
@ -487,5 +483,21 @@ public class ElasticsearchTemplateFacetTests {
assertThat(range.getTotal(), is(40.0)); assertThat(range.getTotal(), is(40.0));
} }
@Test
public void shouldReturnStatisticalFacetForGivenQuery() {
// given
String facetName = "statPublishedYear";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new StatisticalFacetRequestBuilder(facetName).field(PUBLISHED_YEARS).build()
).build();
// when
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
StatisticalResult facet = (StatisticalResult) result.getFacet(facetName);
assertThat(facet.getCount(), is(equalTo(6L)));
assertThat(facet.getMax(), is(equalTo(2002.0)));
assertThat(facet.getMin(), is(equalTo(2000.0)));
}
} }