Range Facet: Fix wrong total computation with multi valued fields by introducing total_count, add min/max stats, closes #832.

This commit is contained in:
kimchy 2011-04-05 00:42:46 +03:00
parent 90a339ad5e
commit 79939222e4
7 changed files with 97 additions and 4 deletions

View File

@ -112,7 +112,10 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
entry.toAsString = in.readUTF();
}
entry.count = in.readVLong();
entry.totalCount = in.readVLong();
entry.total = in.readDouble();
entry.min = in.readDouble();
entry.max = in.readDouble();
entries[i] = entry;
}
}
@ -136,7 +139,10 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
out.writeUTF(entry.toAsString);
}
out.writeVLong(entry.count);
out.writeVLong(entry.totalCount);
out.writeDouble(entry.total);
out.writeDouble(entry.min);
out.writeDouble(entry.max);
}
}
@ -149,7 +155,10 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
static final XContentBuilderString TO_STR = new XContentBuilderString("to_str");
static final XContentBuilderString COUNT = new XContentBuilderString("count");
static final XContentBuilderString TOTAL = new XContentBuilderString("total");
static final XContentBuilderString TOTAL_COUNT = new XContentBuilderString("total_count");
static final XContentBuilderString MEAN = new XContentBuilderString("mean");
static final XContentBuilderString MIN = new XContentBuilderString("min");
static final XContentBuilderString MAX = new XContentBuilderString("max");
}
@Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
@ -171,6 +180,9 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
builder.field(Fields.TO_STR, entry.toAsString);
}
builder.field(Fields.COUNT, entry.count());
builder.field(Fields.MIN, entry.min());
builder.field(Fields.MAX, entry.max());
builder.field(Fields.TOTAL_COUNT, entry.totalCount());
builder.field(Fields.TOTAL, entry.total());
builder.field(Fields.MEAN, entry.mean());
builder.endObject();

View File

@ -47,7 +47,6 @@ public class KeyValueRangeFacetCollector extends AbstractFacetCollector {
private NumericFieldData keyFieldData;
private final FieldDataType valueFieldDataType;
private NumericFieldData valueFieldData;
private final RangeFacet.Entry[] entries;
@ -117,12 +116,26 @@ public class KeyValueRangeFacetCollector extends AbstractFacetCollector {
entry.count++;
if (valueFieldData.multiValued()) {
double[] valuesValues = valueFieldData.doubleValues(docId);
entry.totalCount += valuesValues.length;
for (double valueValue : valuesValues) {
entry.total += valueValue;
if (valueValue < entry.min) {
entry.min = valueValue;
}
if (valueValue > entry.max) {
entry.max = valueValue;
}
}
} else {
double valueValue = valueFieldData.doubleValue(docId);
entry.totalCount++;
entry.total += valueValue;
if (valueValue < entry.min) {
entry.min = valueValue;
}
if (valueValue > entry.max) {
entry.max = valueValue;
}
}
}
}

View File

@ -54,8 +54,11 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
String toAsString;
long count;
long totalCount;
double total;
double min = Double.MAX_VALUE;
double max = Double.MIN_VALUE;
/**
* Internal field used in facet collection
@ -111,6 +114,14 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
return count();
}
public long totalCount() {
return this.totalCount;
}
public long getTotalCount() {
return this.totalCount;
}
public double total() {
return this.total;
}
@ -123,7 +134,7 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
* The mean of this facet interval.
*/
public double mean() {
return total / count;
return total / totalCount;
}
/**
@ -132,5 +143,21 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
public double getMean() {
return mean();
}
public double min() {
return this.min;
}
public double getMin() {
return this.min;
}
public double max() {
return this.max;
}
public double getMax() {
return this.max;
}
}
}

View File

@ -100,7 +100,14 @@ public class RangeFacetCollector extends AbstractFacetCollector {
if (value >= entry.getFrom() && value < entry.getTo()) {
entry.foundInDoc = true;
entry.count++;
entry.totalCount++;
entry.total += value;
if (value < entry.min) {
entry.min = value;
}
if (value > entry.max) {
entry.max = value;
}
}
}
}

View File

@ -159,8 +159,17 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce
agg = geoDistanceFacet;
} else {
for (int i = 0; i < geoDistanceFacet.entries.length; i++) {
agg.entries[i].count += geoDistanceFacet.entries[i].count;
agg.entries[i].total += geoDistanceFacet.entries[i].total;
RangeFacet.Entry aggEntry = agg.entries[i];
RangeFacet.Entry currentEntry = geoDistanceFacet.entries[i];
aggEntry.count += currentEntry.count;
aggEntry.totalCount += currentEntry.totalCount;
aggEntry.total += currentEntry.total;
if (currentEntry.min < aggEntry.min) {
aggEntry.min = currentEntry.min;
}
if (currentEntry.max > aggEntry.max) {
aggEntry.max = currentEntry.max;
}
}
}
}

View File

@ -66,7 +66,14 @@ public class ScriptRangeFacetCollector extends AbstractFacetCollector {
for (RangeFacet.Entry entry : entries) {
if (key >= entry.getFrom() && key < entry.getTo()) {
entry.count++;
entry.totalCount++;
entry.total += value;
if (value < entry.min) {
entry.min = value;
}
if (value > entry.max) {
entry.max = value;
}
}
}
}

View File

@ -1113,16 +1113,25 @@ public class SimpleFacetsTests extends AbstractNodesTests {
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
assertThat(Double.parseDouble(facet.entries().get(0).toAsString()), closeTo(1056, 0.000001));
assertThat(facet.entries().get(0).count(), equalTo(1l));
assertThat(facet.entries().get(0).totalCount(), equalTo(1l));
assertThat(facet.entries().get(0).total(), closeTo(1055, 0.000001));
assertThat(facet.entries().get(0).min(), closeTo(1055, 0.000001));
assertThat(facet.entries().get(0).max(), closeTo(1055, 0.000001));
assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001));
assertThat(Double.parseDouble(facet.entries().get(1).fromAsString()), closeTo(1000, 0.000001));
assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001));
assertThat(Double.parseDouble(facet.entries().get(1).toAsString()), closeTo(1170, 0.000001));
assertThat(facet.entries().get(1).count(), equalTo(2l));
assertThat(facet.entries().get(1).totalCount(), equalTo(2l));
assertThat(facet.entries().get(1).total(), closeTo(1055 + 1065, 0.000001));
assertThat(facet.entries().get(1).min(), closeTo(1055, 0.000001));
assertThat(facet.entries().get(1).max(), closeTo(1065, 0.000001));
assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001));
assertThat(facet.entries().get(2).count(), equalTo(1l));
assertThat(facet.entries().get(2).totalCount(), equalTo(1l));
assertThat(facet.entries().get(2).total(), closeTo(1175, 0.000001));
assertThat(facet.entries().get(2).min(), closeTo(1175, 0.000001));
assertThat(facet.entries().get(2).max(), closeTo(1175, 0.000001));
facet = searchResponse.facets().facet("range2");
assertThat(facet.name(), equalTo("range2"));
@ -1143,14 +1152,23 @@ public class SimpleFacetsTests extends AbstractNodesTests {
assertThat(facet.entries().size(), equalTo(3));
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
assertThat(facet.entries().get(0).count(), equalTo(1l));
assertThat(facet.entries().get(0).totalCount(), equalTo(2l));
assertThat(facet.entries().get(0).total(), closeTo(10 + 11, 0.000001));
assertThat(facet.entries().get(0).min(), closeTo(10, 0.000001));
assertThat(facet.entries().get(0).max(), closeTo(11, 0.000001));
assertThat(facet.entries().get(1).from(), closeTo(1000, 0.000001));
assertThat(facet.entries().get(1).to(), closeTo(1170, 0.000001));
assertThat(facet.entries().get(1).count(), equalTo(2l));
assertThat(facet.entries().get(1).totalCount(), equalTo(4l));
assertThat(facet.entries().get(1).total(), closeTo(62, 0.000001));
assertThat(facet.entries().get(1).min(), closeTo(10, 0.000001));
assertThat(facet.entries().get(1).max(), closeTo(21, 0.000001));
assertThat(facet.entries().get(2).from(), closeTo(1170, 0.000001));
assertThat(facet.entries().get(2).count(), equalTo(1l));
assertThat(facet.entries().get(2).totalCount(), equalTo(2l));
assertThat(facet.entries().get(2).total(), closeTo(61, 0.000001));
assertThat(facet.entries().get(2).min(), closeTo(30, 0.000001));
assertThat(facet.entries().get(2).max(), closeTo(31, 0.000001));
facet = searchResponse.facets().facet("range4");
assertThat(facet.name(), equalTo("range4"));