org.elasticsearch.action.fieldstats.FieldStats Maven / Gradle / Ivy
The newest version!
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.fieldstats;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import java.io.IOException;
public abstract class FieldStats> implements Streamable, ToXContent {
private byte type;
private long maxDoc;
private long docCount;
private long sumDocFreq;
private long sumTotalTermFreq;
protected T minValue;
protected T maxValue;
protected FieldStats() {
}
protected FieldStats(int type, long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq) {
this.type = (byte) type;
this.maxDoc = maxDoc;
this.docCount = docCount;
this.sumDocFreq = sumDocFreq;
this.sumTotalTermFreq = sumTotalTermFreq;
}
byte getType() {
return type;
}
/**
* @return the total number of documents.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public long getMaxDoc() {
return maxDoc;
}
/**
* @return the number of documents that have at least one term for this field, or -1 if this measurement isn't available.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public long getDocCount() {
return docCount;
}
/**
* @return The percentage of documents that have at least one value for this field.
*
* This is a derived statistic and is based on: 'doc_count / max_doc'
*/
public int getDensity() {
if (docCount < 0 || maxDoc <= 0) {
return -1;
}
return (int) (docCount * 100 / maxDoc);
}
/**
* @return the sum of each term's document frequency in this field, or -1 if this measurement isn't available.
* Document frequency is the number of documents containing a particular term.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public long getSumDocFreq() {
return sumDocFreq;
}
/**
* @return the sum of the term frequencies of all terms in this field across all documents, or -1 if this measurement
* isn't available. Term frequency is the total number of occurrences of a term in a particular document and field.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public long getSumTotalTermFreq() {
return sumTotalTermFreq;
}
/**
* @return the lowest value in the field.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public T getMinValue() {
return minValue;
}
/**
* @return the highest value in the field.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public T getMaxValue() {
return maxValue;
}
/**
* @return the lowest value in the field represented as a string.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public abstract String getMinValueAsString();
/**
* @return the highest value in the field represented as a string.
*
* Note that, documents marked as deleted that haven't yet been merged way aren't taken into account.
*/
public abstract String getMaxValueAsString();
/**
* @param value The string to be parsed
* @param optionalFormat A string describing how to parse the specified value. Whether this parameter is supported
* depends on the implementation. If optionalFormat is specified and the implementation
* doesn't support it an {@link UnsupportedOperationException} is thrown
*/
protected abstract T valueOf(String value, String optionalFormat);
/**
* Merges the provided stats into this stats instance.
*/
public void append(FieldStats stats) {
this.maxDoc += stats.maxDoc;
if (stats.docCount == -1) {
this.docCount = -1;
} else if (this.docCount != -1) {
this.docCount += stats.docCount;
}
if (stats.sumDocFreq == -1) {
this.sumDocFreq = -1;
} else if (this.sumDocFreq != -1) {
this.sumDocFreq += stats.sumDocFreq;
}
if (stats.sumTotalTermFreq == -1) {
this.sumTotalTermFreq = -1;
} else if (this.sumTotalTermFreq != -1) {
this.sumTotalTermFreq += stats.sumTotalTermFreq;
}
}
/**
* @return true
if this instance matches with the provided index constraint, otherwise false
is returned
*/
public boolean match(IndexConstraint constraint) {
int cmp;
T value = valueOf(constraint.getValue(), constraint.getOptionalFormat());
if (constraint.getProperty() == IndexConstraint.Property.MIN) {
cmp = minValue.compareTo(value);
} else if (constraint.getProperty() == IndexConstraint.Property.MAX) {
cmp = maxValue.compareTo(value);
} else {
throw new IllegalArgumentException("Unsupported property [" + constraint.getProperty() + "]");
}
switch (constraint.getComparison()) {
case GT:
return cmp > 0;
case GTE:
return cmp >= 0;
case LT:
return cmp < 0;
case LTE:
return cmp <= 0;
default:
throw new IllegalArgumentException("Unsupported comparison [" + constraint.getComparison() + "]");
}
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(Fields.MAX_DOC, maxDoc);
builder.field(Fields.DOC_COUNT, docCount);
builder.field(Fields.DENSITY, getDensity());
builder.field(Fields.SUM_DOC_FREQ, sumDocFreq);
builder.field(Fields.SUM_TOTAL_TERM_FREQ, sumTotalTermFreq);
toInnerXContent(builder);
builder.endObject();
return builder;
}
protected void toInnerXContent(XContentBuilder builder) throws IOException {
builder.field(Fields.MIN_VALUE, getMinValue());
builder.field(Fields.MIN_VALUE_AS_STRING, getMinValueAsString());
builder.field(Fields.MAX_VALUE, getMaxValue());
builder.field(Fields.MAX_VALUE_AS_STRING, getMaxValueAsString());
}
@Override
public void readFrom(StreamInput in) throws IOException {
maxDoc = in.readVLong();
docCount = in.readLong();
sumDocFreq = in.readLong();
sumTotalTermFreq = in.readLong();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeByte(type);
out.writeVLong(maxDoc);
out.writeLong(docCount);
out.writeLong(sumDocFreq);
out.writeLong(sumTotalTermFreq);
}
public static class Long extends FieldStats {
public Long() {
}
public Long(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, long minValue, long maxValue) {
this(0, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, minValue, maxValue);
}
protected Long(int type, long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, long minValue, long maxValue) {
super(type, maxDoc, docCount, sumDocFreq, sumTotalTermFreq);
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
public String getMinValueAsString() {
return String.valueOf(minValue.longValue());
}
@Override
public String getMaxValueAsString() {
return String.valueOf(maxValue.longValue());
}
@Override
public void append(FieldStats stats) {
super.append(stats);
Long other = (Long) stats;
this.minValue = Math.min(other.minValue, minValue);
this.maxValue = Math.max(other.maxValue, maxValue);
}
@Override
protected java.lang.Long valueOf(String value, String optionalFormat) {
if (optionalFormat != null) {
throw new UnsupportedOperationException("custom format isn't supported");
}
return java.lang.Long.valueOf(value);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
minValue = in.readLong();
maxValue = in.readLong();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeLong(minValue);
out.writeLong(maxValue);
}
}
public static final class Float extends FieldStats {
public Float() {
}
public Float(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, float minValue, float maxValue) {
super(1, maxDoc, docCount, sumDocFreq, sumTotalTermFreq);
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
public String getMinValueAsString() {
return String.valueOf(minValue.floatValue());
}
@Override
public String getMaxValueAsString() {
return String.valueOf(maxValue.floatValue());
}
@Override
public void append(FieldStats stats) {
super.append(stats);
Float other = (Float) stats;
this.minValue = Math.min(other.minValue, minValue);
this.maxValue = Math.max(other.maxValue, maxValue);
}
@Override
protected java.lang.Float valueOf(String value, String optionalFormat) {
if (optionalFormat != null) {
throw new UnsupportedOperationException("custom format isn't supported");
}
return java.lang.Float.valueOf(value);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
minValue = in.readFloat();
maxValue = in.readFloat();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeFloat(minValue);
out.writeFloat(maxValue);
}
}
public static final class Double extends FieldStats {
public Double() {
}
public Double(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, double minValue, double maxValue) {
super(2, maxDoc, docCount, sumDocFreq, sumTotalTermFreq);
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
public String getMinValueAsString() {
return String.valueOf(minValue.doubleValue());
}
@Override
public String getMaxValueAsString() {
return String.valueOf(maxValue.doubleValue());
}
@Override
public void append(FieldStats stats) {
super.append(stats);
Double other = (Double) stats;
this.minValue = Math.min(other.minValue, minValue);
this.maxValue = Math.max(other.maxValue, maxValue);
}
@Override
protected java.lang.Double valueOf(String value, String optionalFormat) {
if (optionalFormat != null) {
throw new UnsupportedOperationException("custom format isn't supported");
}
return java.lang.Double.valueOf(value);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
minValue = in.readDouble();
maxValue = in.readDouble();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeDouble(minValue);
out.writeDouble(maxValue);
}
}
public static final class Text extends FieldStats {
public Text() {
}
public Text(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, BytesRef minValue, BytesRef maxValue) {
super(3, maxDoc, docCount, sumDocFreq, sumTotalTermFreq);
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
public String getMinValueAsString() {
return minValue.utf8ToString();
}
@Override
public String getMaxValueAsString() {
return maxValue.utf8ToString();
}
@Override
public void append(FieldStats stats) {
super.append(stats);
Text other = (Text) stats;
if (other.minValue.compareTo(minValue) < 0) {
minValue = other.minValue;
}
if (other.maxValue.compareTo(maxValue) > 0) {
maxValue = other.maxValue;
}
}
@Override
protected BytesRef valueOf(String value, String optionalFormat) {
if (optionalFormat != null) {
throw new UnsupportedOperationException("custom format isn't supported");
}
return new BytesRef(value);
}
@Override
protected void toInnerXContent(XContentBuilder builder) throws IOException {
builder.field(Fields.MIN_VALUE, getMinValueAsString());
builder.field(Fields.MAX_VALUE, getMaxValueAsString());
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
minValue = in.readBytesRef();
maxValue = in.readBytesRef();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBytesRef(minValue);
out.writeBytesRef(maxValue);
}
}
public static final class Date extends Long {
private FormatDateTimeFormatter dateFormatter;
public Date() {
}
public Date(long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, long minValue, long maxValue, FormatDateTimeFormatter dateFormatter) {
super(4, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, minValue, maxValue);
this.dateFormatter = dateFormatter;
}
@Override
public String getMinValueAsString() {
return dateFormatter.printer().print(minValue);
}
@Override
public String getMaxValueAsString() {
return dateFormatter.printer().print(maxValue);
}
@Override
protected java.lang.Long valueOf(String value, String optionalFormat) {
FormatDateTimeFormatter dateFormatter = this.dateFormatter;
if (optionalFormat != null) {
dateFormatter = Joda.forPattern(optionalFormat);
}
return dateFormatter.parser().parseMillis(value);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
dateFormatter = Joda.forPattern(in.readString());
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(dateFormatter.format());
}
}
public static FieldStats read(StreamInput in) throws IOException {
FieldStats stats;
byte type = in.readByte();
switch (type) {
case 0:
stats = new Long();
break;
case 1:
stats = new Float();
break;
case 2:
stats = new Double();
break;
case 3:
stats = new Text();
break;
case 4:
stats = new Date();
break;
default:
throw new IllegalArgumentException("Illegal type [" + type + "]");
}
stats.type = type;
stats.readFrom(in);
return stats;
}
private final static class Fields {
final static XContentBuilderString MAX_DOC = new XContentBuilderString("max_doc");
final static XContentBuilderString DOC_COUNT = new XContentBuilderString("doc_count");
final static XContentBuilderString DENSITY = new XContentBuilderString("density");
final static XContentBuilderString SUM_DOC_FREQ = new XContentBuilderString("sum_doc_freq");
final static XContentBuilderString SUM_TOTAL_TERM_FREQ = new XContentBuilderString("sum_total_term_freq");
final static XContentBuilderString MIN_VALUE = new XContentBuilderString("min_value");
final static XContentBuilderString MIN_VALUE_AS_STRING = new XContentBuilderString("min_value_as_string");
final static XContentBuilderString MAX_VALUE = new XContentBuilderString("max_value");
final static XContentBuilderString MAX_VALUE_AS_STRING = new XContentBuilderString("max_value_as_string");
}
}