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:
parent
90a339ad5e
commit
79939222e4
|
@ -112,7 +112,10 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
|
||||||
entry.toAsString = in.readUTF();
|
entry.toAsString = in.readUTF();
|
||||||
}
|
}
|
||||||
entry.count = in.readVLong();
|
entry.count = in.readVLong();
|
||||||
|
entry.totalCount = in.readVLong();
|
||||||
entry.total = in.readDouble();
|
entry.total = in.readDouble();
|
||||||
|
entry.min = in.readDouble();
|
||||||
|
entry.max = in.readDouble();
|
||||||
entries[i] = entry;
|
entries[i] = entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +139,10 @@ public class InternalRangeFacet implements RangeFacet, InternalFacet {
|
||||||
out.writeUTF(entry.toAsString);
|
out.writeUTF(entry.toAsString);
|
||||||
}
|
}
|
||||||
out.writeVLong(entry.count);
|
out.writeVLong(entry.count);
|
||||||
|
out.writeVLong(entry.totalCount);
|
||||||
out.writeDouble(entry.total);
|
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 TO_STR = new XContentBuilderString("to_str");
|
||||||
static final XContentBuilderString COUNT = new XContentBuilderString("count");
|
static final XContentBuilderString COUNT = new XContentBuilderString("count");
|
||||||
static final XContentBuilderString TOTAL = new XContentBuilderString("total");
|
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 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 {
|
@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.TO_STR, entry.toAsString);
|
||||||
}
|
}
|
||||||
builder.field(Fields.COUNT, entry.count());
|
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.TOTAL, entry.total());
|
||||||
builder.field(Fields.MEAN, entry.mean());
|
builder.field(Fields.MEAN, entry.mean());
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
|
|
|
@ -47,7 +47,6 @@ public class KeyValueRangeFacetCollector extends AbstractFacetCollector {
|
||||||
private NumericFieldData keyFieldData;
|
private NumericFieldData keyFieldData;
|
||||||
|
|
||||||
private final FieldDataType valueFieldDataType;
|
private final FieldDataType valueFieldDataType;
|
||||||
private NumericFieldData valueFieldData;
|
|
||||||
|
|
||||||
private final RangeFacet.Entry[] entries;
|
private final RangeFacet.Entry[] entries;
|
||||||
|
|
||||||
|
@ -117,12 +116,26 @@ public class KeyValueRangeFacetCollector extends AbstractFacetCollector {
|
||||||
entry.count++;
|
entry.count++;
|
||||||
if (valueFieldData.multiValued()) {
|
if (valueFieldData.multiValued()) {
|
||||||
double[] valuesValues = valueFieldData.doubleValues(docId);
|
double[] valuesValues = valueFieldData.doubleValues(docId);
|
||||||
|
entry.totalCount += valuesValues.length;
|
||||||
for (double valueValue : valuesValues) {
|
for (double valueValue : valuesValues) {
|
||||||
entry.total += valueValue;
|
entry.total += valueValue;
|
||||||
|
if (valueValue < entry.min) {
|
||||||
|
entry.min = valueValue;
|
||||||
|
}
|
||||||
|
if (valueValue > entry.max) {
|
||||||
|
entry.max = valueValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double valueValue = valueFieldData.doubleValue(docId);
|
double valueValue = valueFieldData.doubleValue(docId);
|
||||||
|
entry.totalCount++;
|
||||||
entry.total += valueValue;
|
entry.total += valueValue;
|
||||||
|
if (valueValue < entry.min) {
|
||||||
|
entry.min = valueValue;
|
||||||
|
}
|
||||||
|
if (valueValue > entry.max) {
|
||||||
|
entry.max = valueValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,11 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
|
||||||
String toAsString;
|
String toAsString;
|
||||||
|
|
||||||
long count;
|
long count;
|
||||||
|
long totalCount;
|
||||||
|
|
||||||
double total;
|
double total;
|
||||||
|
double min = Double.MAX_VALUE;
|
||||||
|
double max = Double.MIN_VALUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal field used in facet collection
|
* Internal field used in facet collection
|
||||||
|
@ -111,6 +114,14 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
|
||||||
return count();
|
return count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long totalCount() {
|
||||||
|
return this.totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotalCount() {
|
||||||
|
return this.totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
public double total() {
|
public double total() {
|
||||||
return this.total;
|
return this.total;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +134,7 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
|
||||||
* The mean of this facet interval.
|
* The mean of this facet interval.
|
||||||
*/
|
*/
|
||||||
public double mean() {
|
public double mean() {
|
||||||
return total / count;
|
return total / totalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,5 +143,21 @@ public interface RangeFacet extends Facet, Iterable<RangeFacet.Entry> {
|
||||||
public double getMean() {
|
public double getMean() {
|
||||||
return mean();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,14 @@ public class RangeFacetCollector extends AbstractFacetCollector {
|
||||||
if (value >= entry.getFrom() && value < entry.getTo()) {
|
if (value >= entry.getFrom() && value < entry.getTo()) {
|
||||||
entry.foundInDoc = true;
|
entry.foundInDoc = true;
|
||||||
entry.count++;
|
entry.count++;
|
||||||
|
entry.totalCount++;
|
||||||
entry.total += value;
|
entry.total += value;
|
||||||
|
if (value < entry.min) {
|
||||||
|
entry.min = value;
|
||||||
|
}
|
||||||
|
if (value > entry.max) {
|
||||||
|
entry.max = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,8 +159,17 @@ public class RangeFacetProcessor extends AbstractComponent implements FacetProce
|
||||||
agg = geoDistanceFacet;
|
agg = geoDistanceFacet;
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < geoDistanceFacet.entries.length; i++) {
|
for (int i = 0; i < geoDistanceFacet.entries.length; i++) {
|
||||||
agg.entries[i].count += geoDistanceFacet.entries[i].count;
|
RangeFacet.Entry aggEntry = agg.entries[i];
|
||||||
agg.entries[i].total += geoDistanceFacet.entries[i].total;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,14 @@ public class ScriptRangeFacetCollector extends AbstractFacetCollector {
|
||||||
for (RangeFacet.Entry entry : entries) {
|
for (RangeFacet.Entry entry : entries) {
|
||||||
if (key >= entry.getFrom() && key < entry.getTo()) {
|
if (key >= entry.getFrom() && key < entry.getTo()) {
|
||||||
entry.count++;
|
entry.count++;
|
||||||
|
entry.totalCount++;
|
||||||
entry.total += value;
|
entry.total += value;
|
||||||
|
if (value < entry.min) {
|
||||||
|
entry.min = value;
|
||||||
|
}
|
||||||
|
if (value > entry.max) {
|
||||||
|
entry.max = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1113,16 +1113,25 @@ public class SimpleFacetsTests extends AbstractNodesTests {
|
||||||
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
|
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
|
||||||
assertThat(Double.parseDouble(facet.entries().get(0).toAsString()), 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).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).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(facet.entries().get(1).from(), closeTo(1000, 0.000001));
|
||||||
assertThat(Double.parseDouble(facet.entries().get(1).fromAsString()), 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(facet.entries().get(1).to(), closeTo(1170, 0.000001));
|
||||||
assertThat(Double.parseDouble(facet.entries().get(1).toAsString()), 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).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).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).from(), closeTo(1170, 0.000001));
|
||||||
assertThat(facet.entries().get(2).count(), equalTo(1l));
|
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).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");
|
facet = searchResponse.facets().facet("range2");
|
||||||
assertThat(facet.name(), equalTo("range2"));
|
assertThat(facet.name(), equalTo("range2"));
|
||||||
|
@ -1143,14 +1152,23 @@ public class SimpleFacetsTests extends AbstractNodesTests {
|
||||||
assertThat(facet.entries().size(), equalTo(3));
|
assertThat(facet.entries().size(), equalTo(3));
|
||||||
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
|
assertThat(facet.entries().get(0).to(), closeTo(1056, 0.000001));
|
||||||
assertThat(facet.entries().get(0).count(), equalTo(1l));
|
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).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).from(), closeTo(1000, 0.000001));
|
||||||
assertThat(facet.entries().get(1).to(), closeTo(1170, 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).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).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).from(), closeTo(1170, 0.000001));
|
||||||
assertThat(facet.entries().get(2).count(), equalTo(1l));
|
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).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");
|
facet = searchResponse.facets().facet("range4");
|
||||||
assertThat(facet.name(), equalTo("range4"));
|
assertThat(facet.name(), equalTo("range4"));
|
||||||
|
|
Loading…
Reference in New Issue