Terms Facet: Add option include counts where term is missing, closes #632.

This commit is contained in:
kimchy 2011-01-18 21:51:16 +02:00
parent e4a6e99f69
commit 574c455203
49 changed files with 464 additions and 35 deletions

View File

@ -91,6 +91,8 @@ public abstract class FieldData<Doc extends DocFieldData> {
public static interface StringValueInDocProc { public static interface StringValueInDocProc {
void onValue(int docId, String value); void onValue(int docId, String value);
void onMissing(int docId);
} }
/** /**

View File

@ -96,5 +96,7 @@ public abstract class NumericFieldData<Doc extends NumericDocFieldData> extends
public static interface DoubleValueInDocProc { public static interface DoubleValueInDocProc {
void onValue(int docId, double value); void onValue(int docId, double value);
void onMissing(int docId);
} }
} }

View File

@ -111,6 +111,8 @@ public abstract class ByteFieldData extends NumericFieldData<ByteDocFieldData> {
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, byte value); void onValue(int docId, byte value);
void onMissing(int docID);
} }
public static ByteFieldData load(IndexReader reader, String field) throws IOException { public static ByteFieldData load(IndexReader reader, String field) throws IOException {

View File

@ -81,30 +81,45 @@ public class MultiValueByteFieldData extends ByteFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Byte.toString(values[loc])); proc.onValue(docId, Byte.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public double[] doubleValues(int docId) { @Override public double[] doubleValues(int docId) {

View File

@ -64,6 +64,7 @@ public class SingleValueByteFieldData extends ByteFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Byte.toString(values[loc])); proc.onValue(docId, Byte.toString(values[loc]));
@ -72,6 +73,7 @@ public class SingleValueByteFieldData extends ByteFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -80,6 +82,7 @@ public class SingleValueByteFieldData extends ByteFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -111,6 +111,8 @@ public abstract class DoubleFieldData extends NumericFieldData<DoubleDocFieldDat
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, double value); void onValue(int docId, double value);
void onMissing(int docId);
} }
public static DoubleFieldData load(IndexReader reader, String field) throws IOException { public static DoubleFieldData load(IndexReader reader, String field) throws IOException {

View File

@ -70,30 +70,45 @@ public class MultiValueDoubleFieldData extends DoubleFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Double.toString(values[loc])); proc.onValue(docId, Double.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public double[] doubleValues(int docId) { @Override public double[] doubleValues(int docId) {

View File

@ -57,6 +57,7 @@ public class SingleValueDoubleFieldData extends DoubleFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Double.toString(values[loc])); proc.onValue(docId, Double.toString(values[loc]));
@ -65,6 +66,7 @@ public class SingleValueDoubleFieldData extends DoubleFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -73,6 +75,7 @@ public class SingleValueDoubleFieldData extends DoubleFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -111,6 +111,8 @@ public abstract class FloatFieldData extends NumericFieldData<FloatDocFieldData>
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, float value); void onValue(int docId, float value);
void onMissing(int docId);
} }
public static FloatFieldData load(IndexReader reader, String field) throws IOException { public static FloatFieldData load(IndexReader reader, String field) throws IOException {

View File

@ -81,30 +81,45 @@ public class MultiValueFloatFieldData extends FloatFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Float.toString(values[loc])); proc.onValue(docId, Float.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public double[] doubleValues(int docId) { @Override public double[] doubleValues(int docId) {

View File

@ -64,6 +64,7 @@ public class SingleValueFloatFieldData extends FloatFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Float.toString(values[loc])); proc.onValue(docId, Float.toString(values[loc]));
@ -72,6 +73,7 @@ public class SingleValueFloatFieldData extends FloatFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -80,6 +82,7 @@ public class SingleValueFloatFieldData extends FloatFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -111,6 +111,8 @@ public abstract class IntFieldData extends NumericFieldData<IntDocFieldData> {
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, int value); void onValue(int docId, int value);
void onMissing(int docId);
} }
public static IntFieldData load(IndexReader reader, String field) throws IOException { public static IntFieldData load(IndexReader reader, String field) throws IOException {

View File

@ -81,30 +81,45 @@ public class MultiValueIntFieldData extends IntFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Integer.toString(values[loc])); proc.onValue(docId, Integer.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public double[] doubleValues(int docId) { @Override public double[] doubleValues(int docId) {

View File

@ -64,6 +64,7 @@ public class SingleValueIntFieldData extends IntFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Integer.toString(values[loc])); proc.onValue(docId, Integer.toString(values[loc]));
@ -72,6 +73,7 @@ public class SingleValueIntFieldData extends IntFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -80,6 +82,7 @@ public class SingleValueIntFieldData extends IntFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -133,6 +133,8 @@ public abstract class LongFieldData extends NumericFieldData<LongDocFieldData> {
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, long value); void onValue(int docId, long value);
void onMissing(int docId);
} }
public abstract void forEachValueInDoc(int docId, DateValueInDocProc proc); public abstract void forEachValueInDoc(int docId, DateValueInDocProc proc);

View File

@ -97,30 +97,45 @@ public class MultiValueLongFieldData extends LongFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Long.toString(values[loc])); proc.onValue(docId, Long.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DateValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DateValueInDocProc proc) {

View File

@ -74,6 +74,7 @@ public class SingleValueLongFieldData extends LongFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Long.toString(values[loc])); proc.onValue(docId, Long.toString(values[loc]));
@ -82,6 +83,7 @@ public class SingleValueLongFieldData extends LongFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -90,6 +92,7 @@ public class SingleValueLongFieldData extends LongFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -81,30 +81,45 @@ public class MultiValueShortFieldData extends ShortFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, Short.toString(values[loc])); proc.onValue(docId, Short.toString(values[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public double[] doubleValues(int docId) { @Override public double[] doubleValues(int docId) {

View File

@ -111,6 +111,8 @@ public abstract class ShortFieldData extends NumericFieldData<ShortDocFieldData>
public static interface ValueInDocProc { public static interface ValueInDocProc {
void onValue(int docId, short value); void onValue(int docId, short value);
void onMissing(int docId);
} }
public static ShortFieldData load(IndexReader reader, String field) throws IOException { public static ShortFieldData load(IndexReader reader, String field) throws IOException {

View File

@ -64,6 +64,7 @@ public class SingleValueShortFieldData extends ShortFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, Short.toString(values[loc])); proc.onValue(docId, Short.toString(values[loc]));
@ -72,6 +73,7 @@ public class SingleValueShortFieldData extends ShortFieldData {
@Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, DoubleValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
@ -80,6 +82,7 @@ public class SingleValueShortFieldData extends ShortFieldData {
@Override public void forEachValueInDoc(int docId, ValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, ValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -71,12 +71,17 @@ public class MultiValueStringFieldData extends StringFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public String value(int docId) { @Override public String value(int docId) {

View File

@ -66,6 +66,7 @@ public class SingleValueStringFieldData extends StringFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, values[loc]); proc.onValue(docId, values[loc]);

View File

@ -95,12 +95,17 @@ public class MultiValueGeoPointFieldData extends GeoPointFieldData {
} }
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
boolean found = false;
for (int[] ordinal : ordinals) { for (int[] ordinal : ordinals) {
int loc = ordinal[docId]; int loc = ordinal[docId];
if (loc != 0) { if (loc != 0) {
found = true;
proc.onValue(docId, GeoHashUtils.encode(lat[loc], lon[loc])); proc.onValue(docId, GeoHashUtils.encode(lat[loc], lon[loc]));
} }
} }
if (!found) {
proc.onMissing(docId);
}
} }
@Override public GeoPoint value(int docId) { @Override public GeoPoint value(int docId) {

View File

@ -74,6 +74,7 @@ public class SingleValueGeoPointFieldData extends GeoPointFieldData {
@Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) { @Override public void forEachValueInDoc(int docId, StringValueInDocProc proc) {
int loc = ordinals[docId]; int loc = ordinals[docId];
if (loc == 0) { if (loc == 0) {
proc.onMissing(docId);
return; return;
} }
proc.onValue(docId, GeoHashUtils.encode(lat[loc], lon[loc])); proc.onValue(docId, GeoHashUtils.encode(lat[loc], lon[loc]));

View File

@ -107,6 +107,8 @@ public class CountAndTotalHistogramFacetCollector extends AbstractFacetCollector
private final TLongDoubleHashMap totals = new TLongDoubleHashMap(); private final TLongDoubleHashMap totals = new TLongDoubleHashMap();
private int missing;
public HistogramProc(long interval) { public HistogramProc(long interval) {
this.interval = interval; this.interval = interval;
} }
@ -117,6 +119,10 @@ public class CountAndTotalHistogramFacetCollector extends AbstractFacetCollector
totals.adjustOrPutValue(bucket, value, value); totals.adjustOrPutValue(bucket, value, value);
} }
@Override public void onMissing(int docId) {
missing++;
}
public TLongLongHashMap counts() { public TLongLongHashMap counts() {
return counts; return counts;
} }

View File

@ -104,6 +104,8 @@ public class CountHistogramFacetCollector extends AbstractFacetCollector {
private final TLongLongHashMap counts = new TLongLongHashMap(); private final TLongLongHashMap counts = new TLongLongHashMap();
private int missing;
public HistogramProc(long interval) { public HistogramProc(long interval) {
this.interval = interval; this.interval = interval;
} }
@ -113,6 +115,10 @@ public class CountHistogramFacetCollector extends AbstractFacetCollector {
counts.adjustOrPutValue(bucket, 1, 1); counts.adjustOrPutValue(bucket, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public TLongLongHashMap counts() { public TLongLongHashMap counts() {
return counts; return counts;
} }

View File

@ -116,6 +116,8 @@ public class KeyValueScriptHistogramFacetCollector extends AbstractFacetCollecto
private final TLongDoubleHashMap totals = new TLongDoubleHashMap(); private final TLongDoubleHashMap totals = new TLongDoubleHashMap();
private int missing;
public HistogramProc(long interval, SearchScript valueScript) { public HistogramProc(long interval, SearchScript valueScript) {
this.interval = interval; this.interval = interval;
this.valueScript = valueScript; this.valueScript = valueScript;
@ -128,6 +130,10 @@ public class KeyValueScriptHistogramFacetCollector extends AbstractFacetCollecto
totals.adjustOrPutValue(bucket, scriptValue, scriptValue); totals.adjustOrPutValue(bucket, scriptValue, scriptValue);
} }
@Override public void onMissing(int docId) {
missing++;
}
public TLongLongHashMap counts() { public TLongLongHashMap counts() {
return counts; return counts;
} }

View File

@ -88,6 +88,8 @@ public class RangeFacetCollector extends AbstractFacetCollector {
private final RangeFacet.Entry[] entries; private final RangeFacet.Entry[] entries;
private int missing;
public RangeProc(RangeFacet.Entry[] entries) { public RangeProc(RangeFacet.Entry[] entries) {
this.entries = entries; this.entries = entries;
} }
@ -100,5 +102,9 @@ public class RangeFacetCollector extends AbstractFacetCollector {
} }
} }
} }
@Override public void onMissing(int docId) {
missing++;
}
} }
} }

View File

@ -91,6 +91,8 @@ public class StatisticalFacetCollector extends AbstractFacetCollector {
private long count; private long count;
private int missing;
@Override public void onValue(int docId, double value) { @Override public void onValue(int docId, double value) {
if (value < min || Double.isNaN(min)) { if (value < min || Double.isNaN(min)) {
min = value; min = value;
@ -103,6 +105,10 @@ public class StatisticalFacetCollector extends AbstractFacetCollector {
count++; count++;
} }
@Override public void onMissing(int docId) {
missing++;
}
public final double min() { public final double min() {
return min; return min;
} }

View File

@ -97,6 +97,8 @@ public class StatisticalFieldsFacetCollector extends AbstractFacetCollector {
private long count; private long count;
private int missing;
@Override public void onValue(int docId, double value) { @Override public void onValue(int docId, double value) {
if (value < min || Double.isNaN(min)) { if (value < min || Double.isNaN(min)) {
min = value; min = value;
@ -109,6 +111,10 @@ public class StatisticalFieldsFacetCollector extends AbstractFacetCollector {
count++; count++;
} }
@Override public void onMissing(int docId) {
missing++;
}
public final double min() { public final double min() {
return min; return min;
} }

View File

@ -164,6 +164,16 @@ public interface TermsFacet extends Facet, Iterable<TermsFacet.Entry> {
*/ */
ComparatorType getComparatorType(); ComparatorType getComparatorType();
/**
* The number of docs missing a value.
*/
long missingCount();
/**
* The number of docs missing a value.
*/
long getMissingCount();
/** /**
* The terms and counts. * The terms and counts.
*/ */

View File

@ -112,6 +112,8 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<ByteEntry> entries = ImmutableList.of(); Collection<ByteEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -119,12 +121,13 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
InternalByteTermsFacet() { InternalByteTermsFacet() {
} }
public InternalByteTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<ByteEntry> entries) { public InternalByteTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<ByteEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -159,6 +162,14 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
return comparatorType(); return comparatorType();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
@Override public List<ByteEntry> entries() { @Override public List<ByteEntry> entries() {
if (!(entries instanceof List)) { if (!(entries instanceof List)) {
entries = ImmutableList.copyOf(entries); entries = ImmutableList.copyOf(entries);
@ -190,8 +201,10 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
TByteIntHashMap aggregated = aggregateCache.get().get(); TByteIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalByteTermsFacet mFacet = (InternalByteTermsFacet) facet; InternalByteTermsFacet mFacet = (InternalByteTermsFacet) facet;
missing += mFacet.missingCount();
for (ByteEntry entry : mFacet.entries) { for (ByteEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -203,12 +216,14 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
ordered.add(new ByteEntry(it.key(), it.value())); ordered.add(new ByteEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -218,6 +233,7 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (ByteEntry entry : entries) { for (ByteEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -241,6 +257,7 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<ByteEntry>(size); entries = new ArrayList<ByteEntry>(size);
@ -255,6 +272,7 @@ public class InternalByteTermsFacet extends InternalTermsFacet {
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (ByteEntry entry : entries) { for (ByteEntry entry : entries) {

View File

@ -128,7 +128,7 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
TByteIntHashMap facets = aggregator.facets(); TByteIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalByteTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalByteTermsFacet.ByteEntry>of()); return new InternalByteTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalByteTermsFacet.ByteEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalByteTermsFacet.ByteEntry> ordered = new BoundedTreeSet<InternalByteTermsFacet.ByteEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalByteTermsFacet.ByteEntry> ordered = new BoundedTreeSet<InternalByteTermsFacet.ByteEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalByteTermsFacet.ByteEntry(it.key(), it.value())); ordered.add(new InternalByteTermsFacet.ByteEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalByteTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalByteTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -198,6 +198,8 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
private final TByteIntHashMap facets; private final TByteIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TByteIntHashMap facets) { public StaticAggregatorValueProc(TByteIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -206,8 +208,16 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docID) {
missing++;
}
public final TByteIntHashMap facets() { public final TByteIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -115,6 +115,8 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<DoubleEntry> entries = ImmutableList.of(); Collection<DoubleEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -122,12 +124,13 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
InternalDoubleTermsFacet() { InternalDoubleTermsFacet() {
} }
public InternalDoubleTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<DoubleEntry> entries) { public InternalDoubleTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<DoubleEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -177,6 +180,13 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TDoubleIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TDoubleIntHashMap>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TDoubleIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TDoubleIntHashMap>>() {
@Override protected ThreadLocals.CleanableValue<TDoubleIntHashMap> initialValue() { @Override protected ThreadLocals.CleanableValue<TDoubleIntHashMap> initialValue() {
@ -192,9 +202,10 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
InternalDoubleTermsFacet first = (InternalDoubleTermsFacet) facets.get(0); InternalDoubleTermsFacet first = (InternalDoubleTermsFacet) facets.get(0);
TDoubleIntHashMap aggregated = aggregateCache.get().get(); TDoubleIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalDoubleTermsFacet mFacet = (InternalDoubleTermsFacet) facet; InternalDoubleTermsFacet mFacet = (InternalDoubleTermsFacet) facet;
missing += mFacet.missingCount();
for (DoubleEntry entry : mFacet.entries) { for (DoubleEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -206,12 +217,14 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
ordered.add(new DoubleEntry(it.key(), it.value())); ordered.add(new DoubleEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -221,6 +234,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (DoubleEntry entry : entries) { for (DoubleEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -244,6 +258,7 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<DoubleEntry>(size); entries = new ArrayList<DoubleEntry>(size);
@ -256,8 +271,8 @@ public class InternalDoubleTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (DoubleEntry entry : entries) { for (DoubleEntry entry : entries) {

View File

@ -128,7 +128,7 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
TDoubleIntHashMap facets = aggregator.facets(); TDoubleIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalDoubleTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalDoubleTermsFacet.DoubleEntry>of()); return new InternalDoubleTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalDoubleTermsFacet.DoubleEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalDoubleTermsFacet.DoubleEntry> ordered = new BoundedTreeSet<InternalDoubleTermsFacet.DoubleEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalDoubleTermsFacet.DoubleEntry> ordered = new BoundedTreeSet<InternalDoubleTermsFacet.DoubleEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalDoubleTermsFacet.DoubleEntry(it.key(), it.value())); ordered.add(new InternalDoubleTermsFacet.DoubleEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalDoubleTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalDoubleTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -198,6 +198,8 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
private final TDoubleIntHashMap facets; private final TDoubleIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TDoubleIntHashMap facets) { public StaticAggregatorValueProc(TDoubleIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -206,8 +208,16 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TDoubleIntHashMap facets() { public final TDoubleIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -115,6 +115,8 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<FloatEntry> entries = ImmutableList.of(); Collection<FloatEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -122,12 +124,13 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
InternalFloatTermsFacet() { InternalFloatTermsFacet() {
} }
public InternalFloatTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<FloatEntry> entries) { public InternalFloatTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<FloatEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -177,6 +180,13 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TFloatIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TFloatIntHashMap>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TFloatIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TFloatIntHashMap>>() {
@Override protected ThreadLocals.CleanableValue<TFloatIntHashMap> initialValue() { @Override protected ThreadLocals.CleanableValue<TFloatIntHashMap> initialValue() {
@ -192,9 +202,11 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
InternalFloatTermsFacet first = (InternalFloatTermsFacet) facets.get(0); InternalFloatTermsFacet first = (InternalFloatTermsFacet) facets.get(0);
TFloatIntHashMap aggregated = aggregateCache.get().get(); TFloatIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalFloatTermsFacet mFacet = (InternalFloatTermsFacet) facet; InternalFloatTermsFacet mFacet = (InternalFloatTermsFacet) facet;
missing += mFacet.missingCount();
for (FloatEntry entry : mFacet.entries) { for (FloatEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -206,12 +218,14 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
ordered.add(new FloatEntry(it.key(), it.value())); ordered.add(new FloatEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -221,6 +235,7 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (FloatEntry entry : entries) { for (FloatEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -244,6 +259,7 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<FloatEntry>(size); entries = new ArrayList<FloatEntry>(size);
@ -256,8 +272,8 @@ public class InternalFloatTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (FloatEntry entry : entries) { for (FloatEntry entry : entries) {

View File

@ -128,7 +128,7 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
TFloatIntHashMap facets = aggregator.facets(); TFloatIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalFloatTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalFloatTermsFacet.FloatEntry>of()); return new InternalFloatTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalFloatTermsFacet.FloatEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalFloatTermsFacet.FloatEntry> ordered = new BoundedTreeSet<InternalFloatTermsFacet.FloatEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalFloatTermsFacet.FloatEntry> ordered = new BoundedTreeSet<InternalFloatTermsFacet.FloatEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalFloatTermsFacet.FloatEntry(it.key(), it.value())); ordered.add(new InternalFloatTermsFacet.FloatEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalFloatTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalFloatTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -198,6 +198,8 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
private final TFloatIntHashMap facets; private final TFloatIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TFloatIntHashMap facets) { public StaticAggregatorValueProc(TFloatIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -206,8 +208,16 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TFloatIntHashMap facets() { public final TFloatIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -56,6 +56,6 @@ public class IndexNameFacetCollector extends AbstractFacetCollector {
} }
@Override public Facet facet() { @Override public Facet facet() {
return new InternalStringTermsFacet(facetName, "_index", comparatorType, size, Sets.newHashSet(new InternalStringTermsFacet.StringEntry(indexName, count))); return new InternalStringTermsFacet(facetName, "_index", comparatorType, size, Sets.newHashSet(new InternalStringTermsFacet.StringEntry(indexName, count)), 0);
} }
} }

View File

@ -112,6 +112,8 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<IntEntry> entries = ImmutableList.of(); Collection<IntEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -119,12 +121,13 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
InternalIntTermsFacet() { InternalIntTermsFacet() {
} }
public InternalIntTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<IntEntry> entries) { public InternalIntTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<IntEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -174,6 +177,13 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TIntIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TIntIntHashMap>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TIntIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TIntIntHashMap>>() {
@Override protected ThreadLocals.CleanableValue<TIntIntHashMap> initialValue() { @Override protected ThreadLocals.CleanableValue<TIntIntHashMap> initialValue() {
@ -189,9 +199,11 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
InternalIntTermsFacet first = (InternalIntTermsFacet) facets.get(0); InternalIntTermsFacet first = (InternalIntTermsFacet) facets.get(0);
TIntIntHashMap aggregated = aggregateCache.get().get(); TIntIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalIntTermsFacet mFacet = (InternalIntTermsFacet) facet; InternalIntTermsFacet mFacet = (InternalIntTermsFacet) facet;
missing += mFacet.missingCount();
for (IntEntry entry : mFacet.entries) { for (IntEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -203,12 +215,14 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
ordered.add(new IntEntry(it.key(), it.value())); ordered.add(new IntEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -218,6 +232,7 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (IntEntry entry : entries) { for (IntEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -241,6 +256,7 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<IntEntry>(size); entries = new ArrayList<IntEntry>(size);
@ -253,8 +269,8 @@ public class InternalIntTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (IntEntry entry : entries) { for (IntEntry entry : entries) {

View File

@ -128,7 +128,7 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
TIntIntHashMap facets = aggregator.facets(); TIntIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalIntTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalIntTermsFacet.IntEntry>of()); return new InternalIntTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalIntTermsFacet.IntEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalIntTermsFacet.IntEntry> ordered = new BoundedTreeSet<InternalIntTermsFacet.IntEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalIntTermsFacet.IntEntry> ordered = new BoundedTreeSet<InternalIntTermsFacet.IntEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalIntTermsFacet.IntEntry(it.key(), it.value())); ordered.add(new InternalIntTermsFacet.IntEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalIntTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalIntTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -198,6 +198,8 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
private final TIntIntHashMap facets; private final TIntIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TIntIntHashMap facets) { public StaticAggregatorValueProc(TIntIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -206,8 +208,16 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TIntIntHashMap facets() { public final TIntIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -115,6 +115,8 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<LongEntry> entries = ImmutableList.of(); Collection<LongEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -122,12 +124,13 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
InternalLongTermsFacet() { InternalLongTermsFacet() {
} }
public InternalLongTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<LongEntry> entries) { public InternalLongTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<LongEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -177,6 +180,13 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TLongIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TLongIntHashMap>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TLongIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TLongIntHashMap>>() {
@Override protected ThreadLocals.CleanableValue<TLongIntHashMap> initialValue() { @Override protected ThreadLocals.CleanableValue<TLongIntHashMap> initialValue() {
@ -192,9 +202,11 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
InternalLongTermsFacet first = (InternalLongTermsFacet) facets.get(0); InternalLongTermsFacet first = (InternalLongTermsFacet) facets.get(0);
TLongIntHashMap aggregated = aggregateCache.get().get(); TLongIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalLongTermsFacet mFacet = (InternalLongTermsFacet) facet; InternalLongTermsFacet mFacet = (InternalLongTermsFacet) facet;
missing += mFacet.missingCount();
for (LongEntry entry : mFacet.entries) { for (LongEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -206,12 +218,14 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
ordered.add(new LongEntry(it.key(), it.value())); ordered.add(new LongEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -221,6 +235,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (LongEntry entry : entries) { for (LongEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -244,6 +259,7 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<LongEntry>(size); entries = new ArrayList<LongEntry>(size);
@ -256,8 +272,8 @@ public class InternalLongTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (LongEntry entry : entries) { for (LongEntry entry : entries) {

View File

@ -129,7 +129,7 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
TLongIntHashMap facets = aggregator.facets(); TLongIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalLongTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalLongTermsFacet.LongEntry>of()); return new InternalLongTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalLongTermsFacet.LongEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalLongTermsFacet.LongEntry> ordered = new BoundedTreeSet<InternalLongTermsFacet.LongEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalLongTermsFacet.LongEntry> ordered = new BoundedTreeSet<InternalLongTermsFacet.LongEntry>(comparatorType.comparator(), size * numberOfShards);
@ -138,7 +138,7 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalLongTermsFacet.LongEntry(it.key(), it.value())); ordered.add(new InternalLongTermsFacet.LongEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalLongTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalLongTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -199,6 +199,8 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
private final TLongIntHashMap facets; private final TLongIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TLongIntHashMap facets) { public StaticAggregatorValueProc(TLongIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -207,8 +209,16 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TLongIntHashMap facets() { public final TLongIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -112,6 +112,8 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<ShortEntry> entries = ImmutableList.of(); Collection<ShortEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -119,12 +121,13 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
InternalShortTermsFacet() { InternalShortTermsFacet() {
} }
public InternalShortTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<ShortEntry> entries) { public InternalShortTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<ShortEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -174,6 +177,13 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TShortIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TShortIntHashMap>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TShortIntHashMap>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TShortIntHashMap>>() {
@Override protected ThreadLocals.CleanableValue<TShortIntHashMap> initialValue() { @Override protected ThreadLocals.CleanableValue<TShortIntHashMap> initialValue() {
@ -189,9 +199,10 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
InternalShortTermsFacet first = (InternalShortTermsFacet) facets.get(0); InternalShortTermsFacet first = (InternalShortTermsFacet) facets.get(0);
TShortIntHashMap aggregated = aggregateCache.get().get(); TShortIntHashMap aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalShortTermsFacet mFacet = (InternalShortTermsFacet) facet; InternalShortTermsFacet mFacet = (InternalShortTermsFacet) facet;
missing += mFacet.missingCount();
for (ShortEntry entry : mFacet.entries) { for (ShortEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term, entry.count(), entry.count());
} }
@ -203,12 +214,14 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
ordered.add(new ShortEntry(it.key(), it.value())); ordered.add(new ShortEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -218,6 +231,7 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (ShortEntry entry : entries) { for (ShortEntry entry : entries) {
builder.startObject(); builder.startObject();
@ -241,6 +255,7 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<ShortEntry>(size); entries = new ArrayList<ShortEntry>(size);
@ -253,8 +268,8 @@ public class InternalShortTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (ShortEntry entry : entries) { for (ShortEntry entry : entries) {

View File

@ -128,7 +128,7 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
TShortIntHashMap facets = aggregator.facets(); TShortIntHashMap facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalShortTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalShortTermsFacet.ShortEntry>of()); return new InternalShortTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalShortTermsFacet.ShortEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalShortTermsFacet.ShortEntry> ordered = new BoundedTreeSet<InternalShortTermsFacet.ShortEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalShortTermsFacet.ShortEntry> ordered = new BoundedTreeSet<InternalShortTermsFacet.ShortEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalShortTermsFacet.ShortEntry(it.key(), it.value())); ordered.add(new InternalShortTermsFacet.ShortEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalShortTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalShortTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -198,6 +198,8 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
private final TShortIntHashMap facets; private final TShortIntHashMap facets;
private int missing;
public StaticAggregatorValueProc(TShortIntHashMap facets) { public StaticAggregatorValueProc(TShortIntHashMap facets) {
this.facets = facets; this.facets = facets;
} }
@ -206,8 +208,16 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TShortIntHashMap facets() { public final TShortIntHashMap facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -125,7 +125,7 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
TObjectIntHashMap<String> facets = aggregator.facets(); TObjectIntHashMap<String> facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
TermsStringFacetCollector.pushFacets(facets); TermsStringFacetCollector.pushFacets(facets);
return new InternalStringTermsFacet(facetName, arrayToCommaDelimitedString(fieldsNames), comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of()); return new InternalStringTermsFacet(facetName, arrayToCommaDelimitedString(fieldsNames), comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards);
@ -134,7 +134,7 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value())); ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value()));
} }
TermsStringFacetCollector.pushFacets(facets); TermsStringFacetCollector.pushFacets(facets);
return new InternalStringTermsFacet(facetName, arrayToCommaDelimitedString(fieldsNames), comparatorType, size, ordered); return new InternalStringTermsFacet(facetName, arrayToCommaDelimitedString(fieldsNames), comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -189,6 +189,8 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
private final TObjectIntHashMap<String> facets; private final TObjectIntHashMap<String> facets;
private int missing;
public StaticAggregatorValueProc(TObjectIntHashMap<String> facets) { public StaticAggregatorValueProc(TObjectIntHashMap<String> facets) {
this.facets = facets; this.facets = facets;
} }
@ -197,8 +199,16 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TObjectIntHashMap<String> facets() { public final TObjectIntHashMap<String> facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -111,6 +111,8 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
int requiredSize; int requiredSize;
long missing;
Collection<StringEntry> entries = ImmutableList.of(); Collection<StringEntry> entries = ImmutableList.of();
private ComparatorType comparatorType; private ComparatorType comparatorType;
@ -118,12 +120,13 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
InternalStringTermsFacet() { InternalStringTermsFacet() {
} }
public InternalStringTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<StringEntry> entries) { public InternalStringTermsFacet(String name, String fieldName, ComparatorType comparatorType, int requiredSize, Collection<StringEntry> entries, long missing) {
this.name = name; this.name = name;
this.fieldName = fieldName; this.fieldName = fieldName;
this.comparatorType = comparatorType; this.comparatorType = comparatorType;
this.requiredSize = requiredSize; this.requiredSize = requiredSize;
this.entries = entries; this.entries = entries;
this.missing = missing;
} }
@Override public String name() { @Override public String name() {
@ -173,6 +176,13 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
return (Iterator) entries.iterator(); return (Iterator) entries.iterator();
} }
@Override public long missingCount() {
return this.missing;
}
@Override public long getMissingCount() {
return missingCount();
}
private static ThreadLocal<ThreadLocals.CleanableValue<TObjectIntHashMap<String>>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TObjectIntHashMap<String>>>() { private static ThreadLocal<ThreadLocals.CleanableValue<TObjectIntHashMap<String>>> aggregateCache = new ThreadLocal<ThreadLocals.CleanableValue<TObjectIntHashMap<String>>>() {
@Override protected ThreadLocals.CleanableValue<TObjectIntHashMap<String>> initialValue() { @Override protected ThreadLocals.CleanableValue<TObjectIntHashMap<String>> initialValue() {
@ -188,9 +198,10 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
InternalStringTermsFacet first = (InternalStringTermsFacet) facets.get(0); InternalStringTermsFacet first = (InternalStringTermsFacet) facets.get(0);
TObjectIntHashMap<String> aggregated = aggregateCache.get().get(); TObjectIntHashMap<String> aggregated = aggregateCache.get().get();
aggregated.clear(); aggregated.clear();
long missing = 0;
for (Facet facet : facets) { for (Facet facet : facets) {
InternalStringTermsFacet mFacet = (InternalStringTermsFacet) facet; InternalStringTermsFacet mFacet = (InternalStringTermsFacet) facet;
missing += mFacet.missingCount();
for (InternalStringTermsFacet.StringEntry entry : mFacet.entries) { for (InternalStringTermsFacet.StringEntry entry : mFacet.entries) {
aggregated.adjustOrPutValue(entry.term(), entry.count(), entry.count()); aggregated.adjustOrPutValue(entry.term(), entry.count(), entry.count());
} }
@ -202,12 +213,14 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
ordered.add(new StringEntry(it.key(), it.value())); ordered.add(new StringEntry(it.key(), it.value()));
} }
first.entries = ordered; first.entries = ordered;
first.missing = missing;
return first; return first;
} }
static final class Fields { static final class Fields {
static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); static final XContentBuilderString _TYPE = new XContentBuilderString("_type");
static final XContentBuilderString _FIELD = new XContentBuilderString("_field"); static final XContentBuilderString _FIELD = new XContentBuilderString("_field");
static final XContentBuilderString MISSING = new XContentBuilderString("missing");
static final XContentBuilderString TERMS = new XContentBuilderString("terms"); static final XContentBuilderString TERMS = new XContentBuilderString("terms");
static final XContentBuilderString TERM = new XContentBuilderString("term"); static final XContentBuilderString TERM = new XContentBuilderString("term");
static final XContentBuilderString COUNT = new XContentBuilderString("count"); static final XContentBuilderString COUNT = new XContentBuilderString("count");
@ -217,6 +230,7 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
builder.startObject(name); builder.startObject(name);
builder.field(Fields._TYPE, TermsFacet.TYPE); builder.field(Fields._TYPE, TermsFacet.TYPE);
builder.field(Fields._FIELD, fieldName); builder.field(Fields._FIELD, fieldName);
builder.field(Fields.MISSING, missing);
builder.startArray(Fields.TERMS); builder.startArray(Fields.TERMS);
for (Entry entry : entries) { for (Entry entry : entries) {
builder.startObject(); builder.startObject();
@ -240,6 +254,7 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
fieldName = in.readUTF(); fieldName = in.readUTF();
comparatorType = ComparatorType.fromId(in.readByte()); comparatorType = ComparatorType.fromId(in.readByte());
requiredSize = in.readVInt(); requiredSize = in.readVInt();
missing = in.readVLong();
int size = in.readVInt(); int size = in.readVInt();
entries = new ArrayList<StringEntry>(size); entries = new ArrayList<StringEntry>(size);
@ -252,8 +267,8 @@ public class InternalStringTermsFacet extends InternalTermsFacet {
out.writeUTF(name); out.writeUTF(name);
out.writeUTF(fieldName); out.writeUTF(fieldName);
out.writeByte(comparatorType.id()); out.writeByte(comparatorType.id());
out.writeVInt(requiredSize); out.writeVInt(requiredSize);
out.writeVLong(missing);
out.writeVInt(entries.size()); out.writeVInt(entries.size());
for (Entry entry : entries) { for (Entry entry : entries) {

View File

@ -56,6 +56,8 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector
private final TObjectIntHashMap<String> facets; private final TObjectIntHashMap<String> facets;
private int missing;
public ScriptTermsStringFieldFacetCollector(String facetName, int size, InternalStringTermsFacet.ComparatorType comparatorType, SearchContext context, public ScriptTermsStringFieldFacetCollector(String facetName, int size, InternalStringTermsFacet.ComparatorType comparatorType, SearchContext context,
ImmutableSet<String> excluded, Pattern pattern, String scriptLang, String script, Map<String, Object> params) { ImmutableSet<String> excluded, Pattern pattern, String scriptLang, String script, Map<String, Object> params) {
super(facetName); super(facetName);
@ -78,26 +80,39 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector
@Override protected void doCollect(int doc) throws IOException { @Override protected void doCollect(int doc) throws IOException {
Object o = script.execute(doc); Object o = script.execute(doc);
if (o == null) { if (o == null) {
missing++;
return; return;
} }
if (o instanceof Iterable) { if (o instanceof Iterable) {
boolean found = false;
for (Object o1 : ((Iterable) o)) { for (Object o1 : ((Iterable) o)) {
String value = o1.toString(); String value = o1.toString();
if (match(value)) { if (match(value)) {
found = true;
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
} }
if (!found) {
missing++;
}
} else if (o instanceof Object[]) { } else if (o instanceof Object[]) {
boolean found = false;
for (Object o1 : ((Object[]) o)) { for (Object o1 : ((Object[]) o)) {
String value = o1.toString(); String value = o1.toString();
if (match(value)) { if (match(value)) {
found = true;
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
} }
if (!found) {
missing++;
}
} else { } else {
String value = o.toString(); String value = o.toString();
if (match(value)) { if (match(value)) {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} else {
missing++;
} }
} }
} }
@ -115,7 +130,7 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector
@Override public Facet facet() { @Override public Facet facet() {
if (facets.isEmpty()) { if (facets.isEmpty()) {
TermsStringFacetCollector.pushFacets(facets); TermsStringFacetCollector.pushFacets(facets);
return new InternalStringTermsFacet(facetName, sScript, comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of()); return new InternalStringTermsFacet(facetName, sScript, comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of(), missing);
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards);
@ -124,7 +139,7 @@ public class ScriptTermsStringFieldFacetCollector extends AbstractFacetCollector
ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value())); ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value()));
} }
TermsStringFacetCollector.pushFacets(facets); TermsStringFacetCollector.pushFacets(facets);
return new InternalStringTermsFacet(facetName, sScript, comparatorType, size, ordered); return new InternalStringTermsFacet(facetName, sScript, comparatorType, size, ordered, missing);
} }
} }
} }

View File

@ -128,7 +128,7 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
TObjectIntHashMap<String> facets = aggregator.facets(); TObjectIntHashMap<String> facets = aggregator.facets();
if (facets.isEmpty()) { if (facets.isEmpty()) {
pushFacets(facets); pushFacets(facets);
return new InternalStringTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of()); return new InternalStringTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalStringTermsFacet.StringEntry>of(), aggregator.missing());
} else { } else {
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards); BoundedTreeSet<InternalStringTermsFacet.StringEntry> ordered = new BoundedTreeSet<InternalStringTermsFacet.StringEntry>(comparatorType.comparator(), size * numberOfShards);
@ -137,7 +137,7 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value())); ordered.add(new InternalStringTermsFacet.StringEntry(it.key(), it.value()));
} }
pushFacets(facets); pushFacets(facets);
return new InternalStringTermsFacet(facetName, fieldName, comparatorType, size, ordered); return new InternalStringTermsFacet(facetName, fieldName, comparatorType, size, ordered, aggregator.missing());
} }
} }
@ -210,6 +210,8 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
private final TObjectIntHashMap<String> facets; private final TObjectIntHashMap<String> facets;
private int missing = 0;
public StaticAggregatorValueProc(TObjectIntHashMap<String> facets) { public StaticAggregatorValueProc(TObjectIntHashMap<String> facets) {
this.facets = facets; this.facets = facets;
} }
@ -218,8 +220,16 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
facets.adjustOrPutValue(value, 1, 1); facets.adjustOrPutValue(value, 1, 1);
} }
@Override public void onMissing(int docId) {
missing++;
}
public final TObjectIntHashMap<String> facets() { public final TObjectIntHashMap<String> facets() {
return facets; return facets;
} }
public final int missing() {
return this.missing;
}
} }
} }

View File

@ -208,6 +208,47 @@ public class SimpleFacetsTests extends AbstractNodesTests {
assertThat(facet.count(), equalTo(2l)); assertThat(facet.count(), equalTo(2l));
} }
@Test public void testTermsFacetsMissing() throws Exception {
try {
client.admin().indices().prepareDelete("test").execute().actionGet();
} catch (Exception e) {
// ignore
}
client.admin().indices().prepareCreate("test")
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("bstag").field("type", "byte").endObject()
.startObject("shstag").field("type", "short").endObject()
.startObject("istag").field("type", "integer").endObject()
.startObject("lstag").field("type", "long").endObject()
.startObject("fstag").field("type", "float").endObject()
.startObject("dstag").field("type", "double").endObject()
.endObject().endObject().endObject())
.execute().actionGet();
client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
client.prepareIndex("test", "type1").setSource(jsonBuilder().startObject()
.field("stag", "111")
.field("bstag", 111)
.field("shstag", 111)
.field("istag", 111)
.field("lstag", 111)
.field("fstag", 111.1f)
.field("dstag", 111.1)
.endObject()).execute().actionGet();
client.prepareIndex("test", "type1").setSource(jsonBuilder().startObject()
.field("kuku", "kuku")
.endObject()).execute().actionGet();
client.admin().indices().prepareFlush().setRefresh(true).execute().actionGet();
SearchResponse searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addFacet(termsFacet("facet1").field("stag").size(10))
.execute().actionGet();
TermsFacet facet = searchResponse.facets().facet("facet1");
assertThat(facet.missingCount(), equalTo(1l));
}
@Test public void testTermsFacets() throws Exception { @Test public void testTermsFacets() throws Exception {
try { try {
client.admin().indices().prepareDelete("test").execute().actionGet(); client.admin().indices().prepareDelete("test").execute().actionGet();