Include unindexed field in FieldStats response (#21821)

* Include unindexed field in FieldStats response

This change adds non-searchable fields to the FieldStats response. These fields do not have min/max informations but they can be aggregatable. Fields that are only stored in _source (store:no, index:no, doc_values:no) will still be missing since they do not have any useful information to show. Indices and clients must be at least on V_5_2_0 to see this change.
This commit is contained in:
Jim Ferenczi 2016-12-06 13:32:57 +01:00 committed by GitHub
parent a7050b2d56
commit b42ca6bcc9
8 changed files with 527 additions and 238 deletions

View File

@ -20,8 +20,10 @@
package org.elasticsearch.action.fieldstats;
import org.apache.lucene.document.InetAddressPoint;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.StringHelper;
import org.elasticsearch.Version;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
@ -45,9 +47,50 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
private long sumTotalTermFreq;
private boolean isSearchable;
private boolean isAggregatable;
private boolean hasMinMax;
protected T minValue;
protected T maxValue;
/**
* Builds a FieldStats where min and max value are not available for the field.
* @param type The native type of this FieldStats
* @param maxDoc Max number of docs
* @param docCount the number of documents that have at least one term for this field,
* or -1 if this information isn't available for this field.
* @param sumDocFreq the sum of {@link TermsEnum#docFreq()} for all terms in this field,
* or -1 if this information isn't available for this field.
* @param sumTotalTermFreq the sum of {@link TermsEnum#totalTermFreq} for all terms in this field,
* or -1 if this measure isn't available for this field.
* @param isSearchable true if this field is searchable
* @param isAggregatable true if this field is aggregatable
*/
FieldStats(byte type, long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
this.type = type;
this.maxDoc = maxDoc;
this.docCount = docCount;
this.sumDocFreq = sumDocFreq;
this.sumTotalTermFreq = sumTotalTermFreq;
this.isSearchable = isSearchable;
this.isAggregatable = isAggregatable;
this.hasMinMax = false;
}
/**
* Builds a FieldStats with min and max value for the field.
* @param type The native type of this FieldStats
* @param maxDoc Max number of docs
* @param docCount the number of documents that have at least one term for this field,
* or -1 if this information isn't available for this field.
* @param sumDocFreq the sum of {@link TermsEnum#docFreq()} for all terms in this field,
* or -1 if this information isn't available for this field.
* @param sumTotalTermFreq the sum of {@link TermsEnum#totalTermFreq} for all terms in this field,
* or -1 if this measure isn't available for this field.
* @param isSearchable true if this field is searchable
* @param isAggregatable true if this field is aggregatable
* @param minValue the minimum value indexed in this field
* @param maxValue the maximum value indexed in this field
*/
FieldStats(byte type,
long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable, T minValue, T maxValue) {
@ -60,6 +103,7 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
this.sumTotalTermFreq = sumTotalTermFreq;
this.isSearchable = isSearchable;
this.isAggregatable = isAggregatable;
this.hasMinMax = true;
this.minValue = minValue;
this.maxValue = maxValue;
}
@ -85,6 +129,13 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
}
}
/**
* @return true if min/max informations are available for this field
*/
public boolean hasMinMax() {
return hasMinMax;
}
/**
* @return the total number of documents.
*
@ -216,7 +267,13 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
isAggregatable |= other.isAggregatable;
assert type == other.getType();
updateMinMax((T) other.minValue, (T) other.maxValue);
if (hasMinMax && other.hasMinMax) {
updateMinMax((T) other.minValue, (T) other.maxValue);
} else {
hasMinMax = false;
minValue = null;
maxValue = null;
}
}
private void updateMinMax(T min, T max) {
@ -241,7 +298,9 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
builder.field(SUM_TOTAL_TERM_FREQ_FIELD, sumTotalTermFreq);
builder.field(SEARCHABLE_FIELD, isSearchable);
builder.field(AGGREGATABLE_FIELD, isAggregatable);
toInnerXContent(builder);
if (hasMinMax) {
toInnerXContent(builder);
}
builder.endObject();
return builder;
}
@ -262,7 +321,14 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
out.writeLong(sumTotalTermFreq);
out.writeBoolean(isSearchable);
out.writeBoolean(isAggregatable);
writeMinMax(out);
if (out.getVersion().onOrAfter(Version.V_5_2_0_UNRELEASED)) {
out.writeBoolean(hasMinMax);
if (hasMinMax) {
writeMinMax(out);
}
} else {
writeMinMax(out);
}
}
protected abstract void writeMinMax(StreamOutput out) throws IOException;
@ -272,6 +338,9 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
* otherwise <code>false</code> is returned
*/
public boolean match(IndexConstraint constraint) {
if (hasMinMax == false) {
return false;
}
int cmp;
T value = valueOf(constraint.getValue(), constraint.getOptionalFormat());
if (constraint.getProperty() == IndexConstraint.Property.MIN) {
@ -310,6 +379,10 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
if (sumTotalTermFreq != that.sumTotalTermFreq) return false;
if (isSearchable != that.isSearchable) return false;
if (isAggregatable != that.isAggregatable) return false;
if (hasMinMax != that.hasMinMax) return false;
if (hasMinMax == false) {
return true;
}
if (!minValue.equals(that.minValue)) return false;
return maxValue.equals(that.maxValue);
@ -318,10 +391,16 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
@Override
public int hashCode() {
return Objects.hash(type, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, isSearchable, isAggregatable,
minValue, maxValue);
hasMinMax, minValue, maxValue);
}
public static class Long extends FieldStats<java.lang.Long> {
public Long(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
super((byte) 0, maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
public Long(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable,
long minValue, long maxValue) {
@ -357,6 +436,11 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
}
public static class Double extends FieldStats<java.lang.Double> {
public Double(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
super((byte) 1, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, isSearchable, isAggregatable);
}
public Double(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable,
double minValue, double maxValue) {
@ -397,6 +481,12 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
public static class Date extends FieldStats<java.lang.Long> {
private FormatDateTimeFormatter formatter;
public Date(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
super((byte) 2, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, isSearchable, isAggregatable);
this.formatter = null;
}
public Date(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable,
FormatDateTimeFormatter formatter,
@ -439,23 +529,27 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Date that = (Date) o;
return Objects.equals(formatter.format(), that.formatter.format());
return Objects.equals(formatter == null ? null : formatter.format(),
that.formatter == null ? null : that.formatter.format());
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + formatter.format().hashCode();
result = 31 * result + (formatter == null ? 0 : formatter.format().hashCode());
return result;
}
}
public static class Text extends FieldStats<BytesRef> {
public Text(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
super((byte) 3, maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
public Text(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable,
BytesRef minValue, BytesRef maxValue) {
@ -501,6 +595,13 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
}
public static class Ip extends FieldStats<InetAddress> {
public Ip(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable) {
super((byte) 4, maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
public Ip(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq,
boolean isSearchable, boolean isAggregatable,
InetAddress minValue, InetAddress maxValue) {
@ -550,27 +651,50 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
long sumTotalTermFreq = in.readLong();
boolean isSearchable = in.readBoolean();
boolean isAggregatable = in.readBoolean();
boolean hasMinMax = true;
if (in.getVersion().onOrAfter(Version.V_5_2_0_UNRELEASED)) {
hasMinMax = in.readBoolean();
}
switch (type) {
case 0:
return new Long(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
if (hasMinMax) {
return new Long(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, in.readLong(), in.readLong());
} else {
return new Long(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
case 1:
return new Double(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, in.readDouble(), in.readDouble());
if (hasMinMax) {
return new Double(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, in.readDouble(), in.readDouble());
} else {
return new Double(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
case 2:
FormatDateTimeFormatter formatter = Joda.forPattern(in.readString());
return new Date(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, formatter, in.readLong(), in.readLong());
if (hasMinMax) {
FormatDateTimeFormatter formatter = Joda.forPattern(in.readString());
return new Date(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, formatter, in.readLong(), in.readLong());
} else {
return new Date(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
case 3:
return new Text(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, in.readBytesRef(), in.readBytesRef());
if (hasMinMax) {
return new Text(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable, in.readBytesRef(), in.readBytesRef());
} else {
return new Text(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
case 4:
if (hasMinMax == false) {
return new Ip(maxDoc, docCount, sumDocFreq, sumTotalTermFreq,
isSearchable, isAggregatable);
}
int l1 = in.readByte();
byte[] b1 = new byte[l1];
in.readBytes(b1, 0, l1);
@ -599,5 +723,4 @@ public abstract class FieldStats<T> implements Writeable, ToXContent {
private static final String MIN_VALUE_AS_STRING_FIELD = "min_value_as_string";
private static final String MAX_VALUE_FIELD = "max_value";
private static final String MAX_VALUE_AS_STRING_FIELD = "max_value_as_string";
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.fieldstats;
import org.elasticsearch.Version;
import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.common.Nullable;
@ -91,10 +92,21 @@ public class FieldStatsResponse extends BroadcastResponse {
out.writeVInt(indicesMergedFieldStats.size());
for (Map.Entry<String, Map<String, FieldStats>> entry1 : indicesMergedFieldStats.entrySet()) {
out.writeString(entry1.getKey());
out.writeVInt(entry1.getValue().size());
int size = entry1.getValue().size();
if (out.getVersion().before(Version.V_5_2_0_UNRELEASED)) {
// filter fieldstats without min/max information
for (FieldStats stats : entry1.getValue().values()) {
if (stats.hasMinMax() == false) {
size--;
}
}
}
out.writeVInt(size);
for (Map.Entry<String, FieldStats> entry2 : entry1.getValue().entrySet()) {
out.writeString(entry2.getKey());
entry2.getValue().writeTo(out);
if (entry2.getValue().hasMinMax() || out.getVersion().onOrAfter(Version.V_5_2_0_UNRELEASED)) {
out.writeString(entry2.getKey());
entry2.getValue().writeTo(out);
}
}
}
out.writeVInt(conflicts.size());

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.SortedNumericDocValuesField;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.PointValues;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
@ -299,9 +300,13 @@ public class DateFieldMapper extends FieldMapper {
@Override
public FieldStats.Date stats(IndexReader reader) throws IOException {
String field = name();
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(name());
if (fi == null) {
return null;
}
long size = PointValues.size(reader, field);
if (size == 0) {
return null;
return new FieldStats.Date(reader.maxDoc(), 0, -1, -1, isSearchable(), isAggregatable());
}
int docCount = PointValues.getDocCount(reader, field);
byte[] min = PointValues.getMinPackedValue(reader, field);

View File

@ -23,6 +23,7 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.InetAddressPoint;
import org.apache.lucene.document.SortedSetDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
@ -213,9 +214,13 @@ public class IpFieldMapper extends FieldMapper {
@Override
public FieldStats.Ip stats(IndexReader reader) throws IOException {
String field = name();
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(name());
if (fi == null) {
return null;
}
long size = PointValues.size(reader, field);
if (size == 0) {
return null;
return new FieldStats.Ip(reader.maxDoc(), 0, -1, -1, isSearchable(), isAggregatable());
}
int docCount = PointValues.getDocCount(reader, field);
byte[] min = PointValues.getMinPackedValue(reader, field);

View File

@ -20,18 +20,19 @@
package org.elasticsearch.index.mapper;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiFields;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.elasticsearch.action.fieldstats.FieldStats;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.joda.DateMathParser;
@ -375,14 +376,16 @@ public abstract class MappedFieldType extends FieldType {
*/
public FieldStats stats(IndexReader reader) throws IOException {
int maxDoc = reader.maxDoc();
Terms terms = MultiFields.getTerms(reader, name());
if (terms == null) {
FieldInfo fi = MultiFields.getMergedFieldInfos(reader).fieldInfo(name());
if (fi == null) {
return null;
}
Terms terms = MultiFields.getTerms(reader, name());
if (terms == null) {
return new FieldStats.Text(maxDoc, 0, -1, -1, isSearchable(), isAggregatable());
}
FieldStats stats = new FieldStats.Text(maxDoc, terms.getDocCount(),
terms.getSumDocFreq(), terms.getSumTotalTermFreq(),
isSearchable(), isAggregatable(),
terms.getMin(), terms.getMax());
terms.getSumDocFreq(), terms.getSumTotalTermFreq(), isSearchable(), isAggregatable(), terms.getMin(), terms.getMax());
return stats;
}

View File

@ -27,6 +27,7 @@ import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.SortedNumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
@ -227,14 +228,18 @@ public class NumberFieldMapper extends FieldMapper {
@Override
FieldStats.Double stats(IndexReader reader, String fieldName,
boolean isSearchable, boolean isAggregatable) throws IOException {
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(fieldName);
if (fi == null) {
return null;
}
long size = PointValues.size(reader, fieldName);
if (size == 0) {
return null;
return new FieldStats.Double(reader.maxDoc(), 0, -1, -1, isSearchable, isAggregatable);
}
int docCount = PointValues.getDocCount(reader, fieldName);
byte[] min = PointValues.getMinPackedValue(reader, fieldName);
byte[] max = PointValues.getMaxPackedValue(reader, fieldName);
return new FieldStats.Double(reader.maxDoc(),docCount, -1L, size,
return new FieldStats.Double(reader.maxDoc(), docCount, -1L, size,
isSearchable, isAggregatable,
HalfFloatPoint.decodeDimension(min, 0), HalfFloatPoint.decodeDimension(max, 0));
}
@ -311,9 +316,13 @@ public class NumberFieldMapper extends FieldMapper {
@Override
FieldStats.Double stats(IndexReader reader, String fieldName,
boolean isSearchable, boolean isAggregatable) throws IOException {
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(fieldName);
if (fi == null) {
return null;
}
long size = PointValues.size(reader, fieldName);
if (size == 0) {
return null;
return new FieldStats.Double(reader.maxDoc(), 0, -1, -1, isSearchable, isAggregatable);
}
int docCount = PointValues.getDocCount(reader, fieldName);
byte[] min = PointValues.getMinPackedValue(reader, fieldName);
@ -395,9 +404,13 @@ public class NumberFieldMapper extends FieldMapper {
@Override
FieldStats.Double stats(IndexReader reader, String fieldName,
boolean isSearchable, boolean isAggregatable) throws IOException {
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(fieldName);
if (fi == null) {
return null;
}
long size = PointValues.size(reader, fieldName);
if (size == 0) {
return null;
return new FieldStats.Double(reader.maxDoc(),0, -1, -1, isSearchable, isAggregatable);
}
int docCount = PointValues.getDocCount(reader, fieldName);
byte[] min = PointValues.getMinPackedValue(reader, fieldName);
@ -613,9 +626,13 @@ public class NumberFieldMapper extends FieldMapper {
@Override
FieldStats.Long stats(IndexReader reader, String fieldName,
boolean isSearchable, boolean isAggregatable) throws IOException {
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(fieldName);
if (fi == null) {
return null;
}
long size = PointValues.size(reader, fieldName);
if (size == 0) {
return null;
return new FieldStats.Long(reader.maxDoc(), 0, -1, -1, isSearchable, isAggregatable);
}
int docCount = PointValues.getDocCount(reader, fieldName);
byte[] min = PointValues.getMinPackedValue(reader, fieldName);
@ -709,9 +726,13 @@ public class NumberFieldMapper extends FieldMapper {
@Override
FieldStats.Long stats(IndexReader reader, String fieldName,
boolean isSearchable, boolean isAggregatable) throws IOException {
FieldInfo fi = org.apache.lucene.index.MultiFields.getMergedFieldInfos(reader).fieldInfo(fieldName);
if (fi == null) {
return null;
}
long size = PointValues.size(reader, fieldName);
if (size == 0) {
return null;
return new FieldStats.Long(reader.maxDoc(), 0, -1, -1, isSearchable, isAggregatable);
}
int docCount = PointValues.getDocCount(reader, fieldName);
byte[] min = PointValues.getMinPackedValue(reader, fieldName);

View File

@ -20,10 +20,12 @@
package org.elasticsearch.fieldstats;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.Version;
import org.elasticsearch.action.fieldstats.FieldStats;
import org.elasticsearch.action.fieldstats.FieldStatsResponse;
import org.elasticsearch.action.fieldstats.IndexConstraint;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.DateFieldMapper;
@ -46,7 +48,6 @@ import static org.elasticsearch.action.fieldstats.IndexConstraint.Comparison.LTE
import static org.elasticsearch.action.fieldstats.IndexConstraint.Property.MAX;
import static org.elasticsearch.action.fieldstats.IndexConstraint.Property.MIN;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
public class FieldStatsTests extends ESSingleNodeTestCase {
public void testByte() {
@ -73,83 +74,157 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
testNumberRange("field1", "long", -312321312312422L, -312321312312412L);
}
private static String makeType(String type, boolean indexed, boolean docValues, boolean stored) {
return new StringBuilder()
.append("type=").append(type)
.append(",index=").append(indexed)
.append(",doc_values=").append(docValues)
.append(",store=").append(stored).toString();
}
public void testString() {
createIndex("test", Settings.EMPTY, "test", "field", "type=text");
createIndex("test", Settings.EMPTY, "test",
"field_index", makeType("keyword", true, false, false),
"field_dv", makeType("keyword", false, true, false),
"field_stored", makeType("keyword", false, true, true),
"field_source", makeType("keyword", false, false, false));
for (int value = 0; value <= 10; value++) {
client().prepareIndex("test", "test").setSource("field",
String.format(Locale.ENGLISH, "%03d", value)).get();
String keyword = String.format(Locale.ENGLISH, "%03d", value);
client().prepareIndex("test", "test")
.setSource("field_index", keyword,
"field_dv", keyword,
"field_stored", keyword,
"field_source", keyword).get();
}
client().admin().indices().prepareRefresh().get();
FieldStatsResponse result = client().prepareFieldStats().setFields("field").get();
assertThat(result.getAllFieldStats().get("field").getMaxDoc(), equalTo(11L));
assertThat(result.getAllFieldStats().get("field").getDocCount(), equalTo(11L));
assertThat(result.getAllFieldStats().get("field").getDensity(), equalTo(100));
assertThat(result.getAllFieldStats().get("field").getMinValue(),
equalTo(new BytesRef(String.format(Locale.ENGLISH, "%03d", 0))));
assertThat(result.getAllFieldStats().get("field").getMaxValue(),
equalTo(new BytesRef(String.format(Locale.ENGLISH, "%03d", 10))));
assertThat(result.getAllFieldStats().get("field").getMinValueAsString(),
equalTo(String.format(Locale.ENGLISH, "%03d", 0)));
assertThat(result.getAllFieldStats().get("field").getMaxValueAsString(),
equalTo(String.format(Locale.ENGLISH, "%03d", 10)));
assertThat(result.getAllFieldStats().get("field").getDisplayType(),
equalTo("string"));
FieldStatsResponse result = client().prepareFieldStats()
.setFields("field_index", "field_dv", "field_stored", "field_source").get();
assertEquals(result.getAllFieldStats().size(), 3);
for (String field : new String[] {"field_index", "field_dv", "field_stored"}) {
FieldStats stats = result.getAllFieldStats().get(field);
assertEquals(stats.getMaxDoc(), 11L);
assertEquals(stats.getDisplayType(),
"string");
if ("field_index".equals(field)) {
assertEquals(stats.getMinValue(),
new BytesRef(String.format(Locale.ENGLISH, "%03d", 0)));
assertEquals(stats.getMaxValue(),
new BytesRef(String.format(Locale.ENGLISH, "%03d", 10)));
assertEquals(stats.getMinValueAsString(),
String.format(Locale.ENGLISH, "%03d", 0));
assertEquals(stats.getMaxValueAsString(),
String.format(Locale.ENGLISH, "%03d", 10));
assertEquals(stats.getDocCount(), 11L);
assertEquals(stats.getDensity(), 100);
} else {
assertEquals(stats.getDocCount(), 0L);
assertNull(stats.getMinValue());
assertNull(stats.getMaxValue());
assertEquals(stats.getDensity(), 0);
}
}
}
public void testDouble() {
String fieldName = "field";
createIndex("test", Settings.EMPTY, "test", fieldName, "type=double");
createIndex("test", Settings.EMPTY, "test",
"field_index", makeType("double", true, false, false),
"field_dv", makeType("double", false, true, false),
"field_stored", makeType("double", false, true, true),
"field_source", makeType("double", false, false, false));
for (double value = -1; value <= 9; value++) {
client().prepareIndex("test", "test").setSource(fieldName, value).get();
client().prepareIndex("test", "test")
.setSource("field_index", value, "field_dv", value, "field_stored", value, "field_source", value).get();
}
client().admin().indices().prepareRefresh().get();
FieldStatsResponse result = client().prepareFieldStats().setFields(fieldName).get();
assertThat(result.getAllFieldStats().get(fieldName).getMaxDoc(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDocCount(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDensity(), equalTo(100));
assertThat(result.getAllFieldStats().get(fieldName).getMinValue(), equalTo(-1d));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValue(), equalTo(9d));
assertThat(result.getAllFieldStats().get(fieldName).getMinValueAsString(), equalTo(Double.toString(-1)));
assertThat(result.getAllFieldStats().get(fieldName).getDisplayType(), equalTo("float"));
FieldStatsResponse result = client().prepareFieldStats()
.setFields("field_index", "field_dv", "field_stored", "field_source").get();
for (String field : new String[] {"field_index", "field_dv", "field_stored"}) {
FieldStats stats = result.getAllFieldStats().get(field);
assertEquals(stats.getMaxDoc(), 11L);
assertEquals(stats.getDisplayType(), "float");
if ("field_index".equals(field)) {
assertEquals(stats.getDocCount(), 11L);
assertEquals(stats.getDensity(), 100);
assertEquals(stats.getMinValue(), -1d);
assertEquals(stats.getMaxValue(), 9d);
assertEquals(stats.getMinValueAsString(), Double.toString(-1));
} else {
assertEquals(stats.getDocCount(), 0L);
assertNull(stats.getMinValue());
assertNull(stats.getMaxValue());
assertEquals(stats.getDensity(), 0);
}
}
}
public void testHalfFloat() {
String fieldName = "field";
createIndex("test", Settings.EMPTY, "test", fieldName, "type=half_float");
createIndex("test", Settings.EMPTY, "test",
"field_index", makeType("half_float", true, false, false),
"field_dv", makeType("half_float", false, true, false),
"field_stored", makeType("half_float", false, true, true),
"field_source", makeType("half_float", false, false, false));
for (float value = -1; value <= 9; value++) {
client().prepareIndex("test", "test").setSource(fieldName, value).get();
client().prepareIndex("test", "test")
.setSource("field_index", value, "field_dv", value, "field_stored", value, "field_source", value).get();
}
client().admin().indices().prepareRefresh().get();
FieldStatsResponse result = client().prepareFieldStats().setFields(fieldName).get();
assertThat(result.getAllFieldStats().get(fieldName).getMaxDoc(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDocCount(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDensity(), equalTo(100));
assertThat(result.getAllFieldStats().get(fieldName).getMinValue(), equalTo(-1d));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValue(), equalTo(9d));
assertThat(result.getAllFieldStats().get(fieldName).getMinValueAsString(), equalTo(Float.toString(-1)));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValueAsString(), equalTo(Float.toString(9)));
assertThat(result.getAllFieldStats().get(fieldName).getDisplayType(), equalTo("float"));
FieldStatsResponse result = client().prepareFieldStats()
.setFields("field_index", "field_dv", "field_stored", "field_source").get();
for (String field : new String[] {"field_index", "field_dv", "field_stored"}) {
FieldStats stats = result.getAllFieldStats().get(field);
assertEquals(stats.getMaxDoc(), 11L);
assertEquals(stats.getDisplayType(), "float");
if (field.equals("field_index")) {
assertEquals(stats.getDocCount(), 11L);
assertEquals(stats.getDensity(), 100);
assertEquals(stats.getMinValue(), -1d);
assertEquals(stats.getMaxValue(), 9d);
assertEquals(stats.getMinValueAsString(), Float.toString(-1));
assertEquals(stats.getMaxValueAsString(), Float.toString(9));
} else {
assertEquals(stats.getDocCount(), 0L);
assertNull(stats.getMinValue());
assertNull(stats.getMaxValue());
assertEquals(stats.getDensity(), 0);
}
}
}
public void testFloat() {
String fieldName = "field";
createIndex("test", Settings.EMPTY, "test", fieldName, "type=float");
createIndex("test", Settings.EMPTY, "test",
"field_index", makeType("float", true, false, false),
"field_dv", makeType("float", false, true, false),
"field_stored", makeType("float", false, true, true),
"field_source", makeType("float", false, false, false));
for (float value = -1; value <= 9; value++) {
client().prepareIndex("test", "test").setSource(fieldName, value).get();
client().prepareIndex("test", "test")
.setSource("field_index", value, "field_dv", value, "field_stored", value, "field_source", value).get();
}
client().admin().indices().prepareRefresh().get();
FieldStatsResponse result = client().prepareFieldStats().setFields(fieldName).get();
assertThat(result.getAllFieldStats().get(fieldName).getMaxDoc(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDocCount(), equalTo(11L));
assertThat(result.getAllFieldStats().get(fieldName).getDensity(), equalTo(100));
assertThat(result.getAllFieldStats().get(fieldName).getMinValue(), equalTo(-1d));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValue(), equalTo(9d));
assertThat(result.getAllFieldStats().get(fieldName).getMinValueAsString(), equalTo(Float.toString(-1)));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValueAsString(), equalTo(Float.toString(9)));
FieldStatsResponse result = client().prepareFieldStats()
.setFields("field_index", "field_dv", "field_stored", "field_source").get();
for (String field : new String[]{"field_index", "field_dv", "field_stored"}) {
FieldStats stats = result.getAllFieldStats().get(field);
assertEquals(stats.getMaxDoc(), 11L);
assertEquals(stats.getDisplayType(), "float");
if (field.equals("field_index")) {
assertEquals(stats.getDocCount(), 11L);
assertEquals(stats.getDensity(), 100);
assertEquals(stats.getMinValue(), -1d);
assertEquals(stats.getMaxValue(), 9d);
assertEquals(stats.getMinValueAsString(), Float.toString(-1));
assertEquals(stats.getMaxValueAsString(), Float.toString(9));
} else {
assertEquals(stats.getDocCount(), 0L);
assertNull(stats.getMinValue());
assertNull(stats.getMaxValue());
assertEquals(stats.getDensity(), 0);
}
}
}
private void testNumberRange(String fieldName, String fieldType, long min, long max) {
@ -166,21 +241,21 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
FieldStatsResponse result = client().prepareFieldStats().setFields(fieldName).get();
long numDocs = max - min + 1;
assertThat(result.getAllFieldStats().get(fieldName).getMaxDoc(), equalTo(numDocs));
assertThat(result.getAllFieldStats().get(fieldName).getDocCount(), equalTo(numDocs));
assertThat(result.getAllFieldStats().get(fieldName).getDensity(), equalTo(100));
assertThat(result.getAllFieldStats().get(fieldName).getMinValue(), equalTo(min));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValue(), equalTo(max));
assertThat(result.getAllFieldStats().get(fieldName).getMinValueAsString(),
equalTo(java.lang.Long.toString(min)));
assertThat(result.getAllFieldStats().get(fieldName).getMaxValueAsString(),
equalTo(java.lang.Long.toString(max)));
assertThat(result.getAllFieldStats().get(fieldName).isSearchable(), equalTo(true));
assertThat(result.getAllFieldStats().get(fieldName).isAggregatable(), equalTo(true));
assertEquals(result.getAllFieldStats().get(fieldName).getMaxDoc(), numDocs);
assertEquals(result.getAllFieldStats().get(fieldName).getDocCount(), numDocs);
assertEquals(result.getAllFieldStats().get(fieldName).getDensity(), 100);
assertEquals(result.getAllFieldStats().get(fieldName).getMinValue(), min);
assertEquals(result.getAllFieldStats().get(fieldName).getMaxValue(), max);
assertEquals(result.getAllFieldStats().get(fieldName).getMinValueAsString(),
java.lang.Long.toString(min));
assertEquals(result.getAllFieldStats().get(fieldName).getMaxValueAsString(),
java.lang.Long.toString(max));
assertEquals(result.getAllFieldStats().get(fieldName).isSearchable(), true);
assertEquals(result.getAllFieldStats().get(fieldName).isAggregatable(), true);
if (fieldType.equals("float") || fieldType.equals("double") || fieldType.equals("half-float")) {
assertThat(result.getAllFieldStats().get(fieldName).getDisplayType(), equalTo("float"));
assertEquals(result.getAllFieldStats().get(fieldName).getDisplayType(), "float");
} else {
assertThat(result.getAllFieldStats().get(fieldName).getDisplayType(), equalTo("integer"));
assertEquals(result.getAllFieldStats().get(fieldName).getDisplayType(), "integer");
}
client().admin().indices().prepareDelete("test").get();
@ -193,18 +268,19 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
stats.add(new FieldStats.Long(1, 1L, 1L, 1L, true, false, 1L, 1L));
stats.add(new FieldStats.Long(1, 1L, 1L, 1L, true, false, 1L, 1L));
stats.add(new FieldStats.Long(1, 1L, 1L, 1L, true, false, 1L, 1L));
stats.add(new FieldStats.Long(0, 0, 0, 0, false, false));
FieldStats stat = new FieldStats.Long(1, 1L, 1L, 1L, true, false, 1L, 1L);
for (FieldStats otherStat : stats) {
stat.accumulate(otherStat);
}
assertThat(stat.getMaxDoc(), equalTo(4L));
assertThat(stat.getDocCount(), equalTo(4L));
assertThat(stat.getSumDocFreq(), equalTo(4L));
assertThat(stat.getSumTotalTermFreq(), equalTo(4L));
assertThat(stat.isSearchable(), equalTo(true));
assertThat(stat.isAggregatable(), equalTo(false));
assertThat(stat.getDisplayType(), equalTo("integer"));
assertEquals(stat.getMaxDoc(), 4L);
assertEquals(stat.getDocCount(), 4L);
assertEquals(stat.getSumDocFreq(), 4L);
assertEquals(stat.getSumTotalTermFreq(), 4L);
assertEquals(stat.isSearchable(), true);
assertEquals(stat.isAggregatable(), false);
assertEquals(stat.getDisplayType(), "integer");
}
public void testMerge_notAvailable() {
@ -217,26 +293,28 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
for (FieldStats otherStat : stats) {
stat.accumulate(otherStat);
}
assertThat(stat.getMaxDoc(), equalTo(4L));
assertThat(stat.getDocCount(), equalTo(-1L));
assertThat(stat.getSumDocFreq(), equalTo(-1L));
assertThat(stat.getSumTotalTermFreq(), equalTo(-1L));
assertThat(stat.isSearchable(), equalTo(true));
assertThat(stat.isAggregatable(), equalTo(true));
assertThat(stat.getDisplayType(), equalTo("integer"));
assertEquals(stat.getMaxDoc(), 4L);
assertEquals(stat.getDocCount(), -1L);
assertEquals(stat.getSumDocFreq(), -1L);
assertEquals(stat.getSumTotalTermFreq(), -1L);
assertEquals(stat.isSearchable(), true);
assertEquals(stat.isAggregatable(), true);
assertEquals(stat.getDisplayType(), "integer");
stats.add(new FieldStats.Long(1, -1L, -1L, -1L, true, true, 1L, 1L));
stats.add(new FieldStats.Long(1, -1L, -1L, -1L, false, true));
stat = stats.remove(0);
for (FieldStats otherStat : stats) {
stat.accumulate(otherStat);
}
assertThat(stat.getMaxDoc(), equalTo(4L));
assertThat(stat.getDocCount(), equalTo(-1L));
assertThat(stat.getSumDocFreq(), equalTo(-1L));
assertThat(stat.getSumTotalTermFreq(), equalTo(-1L));
assertThat(stat.isSearchable(), equalTo(true));
assertThat(stat.isAggregatable(), equalTo(true));
assertThat(stat.getDisplayType(), equalTo("integer"));
assertEquals(stat.getMaxDoc(), 4L);
assertEquals(stat.getDocCount(), -1L);
assertEquals(stat.getSumDocFreq(), -1L);
assertEquals(stat.getSumTotalTermFreq(), -1L);
assertEquals(stat.isSearchable(), true);
assertEquals(stat.isAggregatable(), true);
assertEquals(stat.getDisplayType(), "integer");
assertNull(stat.getMaxValue());
assertNull(stat.getMinValue());
}
public void testNumberFiltering() {
@ -250,9 +328,9 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
.setFields("value")
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(2));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), equalTo(1L));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), equalTo(3L));
assertEquals(response.getIndicesMergedFieldStats().size(), 2);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), 1L);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), 3L);
response = client().prepareFieldStats()
.setFields("value")
@ -260,7 +338,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "0"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -268,7 +346,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LT, "1"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -276,8 +354,8 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "1"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), equalTo(1L));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), 1L);
response = client().prepareFieldStats()
.setFields("value")
@ -285,8 +363,8 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), equalTo(1L));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), 1L);
response = client().prepareFieldStats()
.setFields("value")
@ -294,7 +372,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -302,8 +380,8 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "3"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), equalTo(3L));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), 3L);
response = client().prepareFieldStats()
.setFields("value")
@ -311,8 +389,8 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "4"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), equalTo(3L));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), 3L);
response = client().prepareFieldStats()
.setFields("value")
@ -320,7 +398,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "4"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -328,9 +406,9 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "3"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(2));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), equalTo(1L));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), equalTo(3L));
assertEquals(response.getIndicesMergedFieldStats().size(), 2);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(), 1L);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(), 3L);
response = client().prepareFieldStats()
.setFields("value")
@ -338,7 +416,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LT, "3"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
}
public void testDateFiltering() {
@ -347,8 +425,9 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
DateTime dateTime2 = new DateTime(2014, 1, 2, 0, 0, 0, 0, DateTimeZone.UTC);
String dateTime2Str = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.parser().print(dateTime2);
createIndex("test1", Settings.EMPTY, "type", "value", "type=date");
client().prepareIndex("test1", "test").setSource("value", dateTime1Str).get();
createIndex("test1", Settings.EMPTY, "type", "value", "type=date", "value2", "type=date,index=false");
client().prepareIndex("test1", "test")
.setSource("value", dateTime1Str, "value2", dateTime1Str).get();
createIndex("test2", Settings.EMPTY, "type", "value", "type=date");
client().prepareIndex("test2", "test").setSource("value", dateTime2Str).get();
client().admin().indices().prepareRefresh().get();
@ -357,17 +436,17 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
.setFields("value")
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(2));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
equalTo(dateTime1.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
equalTo(dateTime2.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
equalTo(dateTime1Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo(dateTime2Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 2);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
dateTime1.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
dateTime2.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
dateTime1Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
dateTime2Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
"date");
response = client().prepareFieldStats()
.setFields("value")
@ -375,7 +454,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2013-12-31T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -383,13 +462,13 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2014-01-01T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
equalTo(dateTime1.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
equalTo(dateTime1Str));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
dateTime1.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
dateTime1Str);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getDisplayType(),
"date");
response = client().prepareFieldStats()
.setFields("value")
@ -397,11 +476,11 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2014-01-02T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
equalTo(dateTime2.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo(dateTime2Str));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
dateTime2.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
dateTime2Str);
response = client().prepareFieldStats()
.setFields("value")
@ -409,7 +488,7 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2014-01-03T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
response = client().prepareFieldStats()
.setFields("value")
@ -417,47 +496,53 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, "2014-01-02T01:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
equalTo(dateTime2.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo(dateTime2Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
dateTime2.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
dateTime2Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
"date");
response = client().prepareFieldStats()
.setFields("value")
.setIndexContraints(new IndexConstraint("value", MIN, GTE, "2014-01-01T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(2));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
equalTo(dateTime1.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
equalTo(dateTime2.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
equalTo(dateTime1Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo(dateTime2Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 2);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
dateTime1.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
dateTime2.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
dateTime1Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
dateTime2Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
"date");
response = client().prepareFieldStats()
.setFields("value")
.setIndexContraints(new IndexConstraint("value", MAX, LTE, "2014-01-02T00:00:00.000Z"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(2));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
equalTo(dateTime1.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
equalTo(dateTime2.getMillis()));
assertThat(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
equalTo(dateTime1Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo(dateTime2Str));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 2);
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValue(),
dateTime1.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValue(),
dateTime2.getMillis());
assertEquals(response.getIndicesMergedFieldStats().get("test1").get("value").getMinValueAsString(),
dateTime1Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
dateTime2Str);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(), "date");
response = client().prepareFieldStats()
.setFields("value2")
.setIndexContraints(new IndexConstraint("value2", MAX, LTE, "2014-01-02T00:00:00.000Z"))
.setLevel("indices")
.get();
assertEquals(response.getIndicesMergedFieldStats().size(), 0);
}
public void testDateFiltering_optionalFormat() {
@ -476,11 +561,11 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
new IndexConstraint("value", MAX, LTE, String.valueOf(dateTime2.getMillis()), "epoch_millis"))
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
equalTo("2014-01-02T00:00:00.000Z"));
assertThat(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
equalTo("date"));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getMinValueAsString(),
"2014-01-02T00:00:00.000Z");
assertEquals(response.getIndicesMergedFieldStats().get("test2").get("value").getDisplayType(),
"date");
try {
client().prepareFieldStats()
@ -501,8 +586,8 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
.setFields("*")
.setLevel("indices")
.get();
assertThat(response.getIndicesMergedFieldStats().size(), equalTo(1));
assertThat(response.getIndicesMergedFieldStats().get("test1").size(), equalTo(0));
assertEquals(response.getIndicesMergedFieldStats().size(), 1);
assertEquals(response.getIndicesMergedFieldStats().get("test1").size(), 0);
}
public void testMetaFieldsNotIndexed() {
@ -513,56 +598,91 @@ public class FieldStatsTests extends ESSingleNodeTestCase {
FieldStatsResponse response = client().prepareFieldStats()
.setFields("_id", "_type")
.get();
assertThat(response.getAllFieldStats().size(), equalTo(1));
assertThat(response.getAllFieldStats().get("_type").isSearchable(), equalTo(true));
assertThat(response.getAllFieldStats().get("_type").isAggregatable(), equalTo(true));
assertEquals(response.getAllFieldStats().size(), 1);
assertEquals(response.getAllFieldStats().get("_type").isSearchable(), true);
assertEquals(response.getAllFieldStats().get("_type").isAggregatable(), true);
}
public void testSerialization() throws IOException {
for (int i = 0; i < 20; i++) {
assertSerialization(randomFieldStats());
for (Version version : new Version[] {Version.CURRENT, Version.V_5_0_1}){
for (int i = 0; i < 20; i++) {
assertSerialization(randomFieldStats(version.onOrAfter(Version.V_5_2_0_UNRELEASED)), version);
}
}
}
/**
* creates a random field stats which does not guarantee that {@link FieldStats#maxValue} is greater than {@link FieldStats#minValue}
**/
private FieldStats randomFieldStats() throws UnknownHostException {
private FieldStats randomFieldStats(boolean withNullMinMax) throws UnknownHostException {
int type = randomInt(5);
switch (type) {
case 0:
return new FieldStats.Long(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), randomLong(), randomLong());
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Long(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Long(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), randomLong(), randomLong());
}
case 1:
return new FieldStats.Double(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), randomDouble(), randomDouble());
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Double(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Double(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), randomDouble(), randomDouble());
}
case 2:
return new FieldStats.Date(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), Joda.forPattern("basicDate"),
new Date().getTime(), new Date().getTime());
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Date(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Date(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(), Joda.forPattern("basicDate"),
new Date().getTime(), new Date().getTime());
}
case 3:
return new FieldStats.Text(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
new BytesRef(randomAsciiOfLength(10)), new BytesRef(randomAsciiOfLength(20)));
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Text(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Text(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
new BytesRef(randomAsciiOfLength(10)), new BytesRef(randomAsciiOfLength(20)));
}
case 4:
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
InetAddress.getByName("::1"), InetAddress.getByName("::1"));
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
InetAddress.getByName("::1"), InetAddress.getByName("::1"));
}
case 5:
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
InetAddress.getByName("1.2.3.4"), InetAddress.getByName("1.2.3.4"));
if (withNullMinMax && randomBoolean()) {
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean());
} else {
return new FieldStats.Ip(randomPositiveLong(), randomPositiveLong(), randomPositiveLong(),
randomPositiveLong(), randomBoolean(), randomBoolean(),
InetAddress.getByName("1.2.3.4"), InetAddress.getByName("1.2.3.4"));
}
default:
throw new IllegalArgumentException("Invalid type");
}
}
private void assertSerialization(FieldStats stats) throws IOException {
private void assertSerialization(FieldStats stats, Version version) throws IOException {
BytesStreamOutput output = new BytesStreamOutput();
output.setVersion(version);
stats.writeTo(output);
output.flush();
FieldStats deserializedStats = FieldStats.readFrom(output.bytes().streamInput());
assertThat(stats, equalTo(deserializedStats));
assertThat(stats.hashCode(), equalTo(deserializedStats.hashCode()));
StreamInput input = output.bytes().streamInput();
input.setVersion(version);
FieldStats deserializedStats = FieldStats.readFrom(input);
assertEquals(stats, deserializedStats);
assertEquals(stats.hashCode(), deserializedStats.hashCode());
}
}

View File

@ -299,7 +299,7 @@ Response:
Field stats index constraints allows to omit all field stats for indices that don't match with the constraint. An index
constraint can exclude indices' field stats based on the `min_value` and `max_value` statistic. This option is only
useful if the `level` option is set to `indices`.
useful if the `level` option is set to `indices`. Fields that are not indexed (not searchable) are always omitted when an index constraint is defined.
For example index constraints can be useful to find out the min and max value of a particular property of your data in
a time based scenario. The following request only returns field stats for the `answer_count` property for indices