If matching root doc's inner objects don't match the `nested_filter` then the `missing` value should be used to sort the root doc.

Closes #3020
This commit is contained in:
Martijn van Groningen 2013-05-14 23:56:21 +02:00
parent 2779967279
commit 42d5bdd337
18 changed files with 344 additions and 241 deletions

View File

@ -66,4 +66,9 @@ public final class ByteValuesComparator extends LongValuesComparatorBase<Byte> {
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = (byte) missingValue;
}
}

View File

@ -66,4 +66,9 @@ public final class DoubleValuesComparator extends DoubleValuesComparatorBase<Dou
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = missingValue;
}
}

View File

@ -61,6 +61,11 @@ abstract class DoubleValuesComparatorBase<T extends Number> extends NumberCompar
return this;
}
@Override
public int compareBottomMissing() {
return compare(bottom, missingValue);
}
static final int compare(double left, double right) {
return Double.compare(left, right);
}

View File

@ -66,4 +66,9 @@ public final class FloatValuesComparator extends DoubleValuesComparatorBase<Floa
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = (float) missingValue;
}
}

View File

@ -72,4 +72,9 @@ public final class IntValuesComparator extends LongValuesComparatorBase<Integer>
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = (int) missingValue;
}
}

View File

@ -65,4 +65,9 @@ public final class LongValuesComparator extends LongValuesComparatorBase<Long> {
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = missingValue;
}
}

View File

@ -72,6 +72,11 @@ abstract class LongValuesComparatorBase<T extends Number> extends NumberComparat
return this;
}
@Override
public int compareBottomMissing() {
return compare(bottom, missingValue);
}
private static final class MultiValueWrapper extends LongValues.Filtered {
private final SortMode sortMode;

View File

@ -42,4 +42,19 @@ public abstract class NumberComparatorBase<T> extends FieldComparator<T> {
* @param divisor The specified divisor
*/
public abstract void divide(int slot, int divisor);
/**
* Assigns the underlying missing value to the specified slot, if the actual implementation supports missing value.
*
* @param slot The slot to assign the the missing value to.
*/
public abstract void missing(int slot);
/**
* Compares the missing value to the bottom.
*
* @return any N < 0 if the bottom value is not competitive with the missing value, any N > 0 if the
* bottom value is competitive with the missing value and 0 if they are equal.
*/
public abstract int compareBottomMissing();
}

View File

@ -68,4 +68,9 @@ public final class ShortValuesComparator extends LongValuesComparatorBase<Short>
public void divide(int slot, int divisor) {
values[slot] /= divisor;
}
@Override
public void missing(int slot) {
values[slot] = (short) missingValue;
}
}

View File

@ -59,9 +59,9 @@ public class NestedFieldComparatorSource extends IndexFieldData.XFieldComparator
case MIN:
return new NestedFieldComparator.Lowest(wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, numHits);
case SUM:
return new Sum((NumberComparatorBase) wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, numHits);
return new NestedFieldComparator.Sum((NumberComparatorBase) wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, numHits);
case AVG:
return new Avg((NumberComparatorBase) wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, numHits);
return new NestedFieldComparator.Avg((NumberComparatorBase) wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, numHits);
default:
throw new ElasticSearchIllegalArgumentException(
String.format("Unsupported sort_mode[%s] for nested type", sortMode)
@ -73,167 +73,9 @@ public class NestedFieldComparatorSource extends IndexFieldData.XFieldComparator
public SortField.Type reducedType() {
return wrappedSource.reducedType();
}
}
class Sum extends FieldComparator {
final Filter rootDocumentsFilter;
final Filter innerDocumentsFilter;
final int spareSlot;
NumberComparatorBase wrappedComparator;
FixedBitSet rootDocuments;
FixedBitSet innerDocuments;
int bottomSlot;
Sum(NumberComparatorBase wrappedComparator, Filter rootDocumentsFilter, Filter innerDocumentsFilter, int spareSlot) {
this.wrappedComparator = wrappedComparator;
this.rootDocumentsFilter = rootDocumentsFilter;
this.innerDocumentsFilter = innerDocumentsFilter;
this.spareSlot = spareSlot;
}
@Override
public int compare(int slot1, int slot2) {
return wrappedComparator.compare(slot1, slot2);
}
@Override
public void setBottom(int slot) {
wrappedComparator.setBottom(slot);
this.bottomSlot = slot;
}
@Override
public FieldComparator setNextReader(AtomicReaderContext context) throws IOException {
DocIdSet innerDocuments = innerDocumentsFilter.getDocIdSet(context, null);
if (DocIdSets.isEmpty(innerDocuments)) {
this.innerDocuments = null;
} else if (innerDocuments instanceof FixedBitSet) {
this.innerDocuments = (FixedBitSet) innerDocuments;
} else {
this.innerDocuments = DocIdSets.toFixedBitSet(innerDocuments.iterator(), context.reader().maxDoc());
}
DocIdSet rootDocuments = rootDocumentsFilter.getDocIdSet(context, null);
if (DocIdSets.isEmpty(rootDocuments)) {
this.rootDocuments = null;
} else if (rootDocuments instanceof FixedBitSet) {
this.rootDocuments = (FixedBitSet) rootDocuments;
} else {
this.rootDocuments = DocIdSets.toFixedBitSet(rootDocuments.iterator(), context.reader().maxDoc());
}
wrappedComparator = (NumberComparatorBase) wrappedComparator.setNextReader(context);
return this;
}
@Override
public Object value(int slot) {
return wrappedComparator.value(slot);
}
@Override
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
}
wrappedComparator.copy(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
}
return compare(bottomSlot, spareSlot);
}
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return;
}
wrappedComparator.copy(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
}
}
@Override
public int compareDocToValue(int rootDoc, Object value) throws IOException {
throw new UnsupportedOperationException("compareDocToValue() not used for sorting in ES");
}
}
final class Avg extends Sum {
Avg(NumberComparatorBase wrappedComparator, Filter rootDocumentsFilter, Filter innerDocumentsFilter, int spareSlot) {
super(wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, spareSlot);
}
@Override
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
}
int counter = 1;
wrappedComparator.copy(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
counter++;
}
wrappedComparator.divide(spareSlot, counter);
return compare(bottomSlot, spareSlot);
}
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return;
}
int counter = 1;
wrappedComparator.copy(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
counter++;
}
wrappedComparator.divide(slot, counter);
}
}
// Move to Lucene join module
abstract class NestedFieldComparator extends FieldComparator {
final Filter rootDocumentsFilter;
@ -243,6 +85,7 @@ abstract class NestedFieldComparator extends FieldComparator {
FieldComparator wrappedComparator;
FixedBitSet rootDocuments;
FixedBitSet innerDocuments;
int bottomSlot;
NestedFieldComparator(FieldComparator wrappedComparator, Filter rootDocumentsFilter, Filter innerDocumentsFilter, int spareSlot) {
this.wrappedComparator = wrappedComparator;
@ -252,13 +95,14 @@ abstract class NestedFieldComparator extends FieldComparator {
}
@Override
public int compare(int slot1, int slot2) {
public final int compare(int slot1, int slot2) {
return wrappedComparator.compare(slot1, slot2);
}
@Override
public void setBottom(int slot) {
public final void setBottom(int slot) {
wrappedComparator.setBottom(slot);
this.bottomSlot = slot;
}
@Override
@ -285,10 +129,15 @@ abstract class NestedFieldComparator extends FieldComparator {
}
@Override
public Object value(int slot) {
public final Object value(int slot) {
return wrappedComparator.value(slot);
}
@Override
public final int compareDocToValue(int rootDoc, Object value) throws IOException {
throw new UnsupportedOperationException("compareDocToValue() not used for sorting in ES");
}
final static class Lowest extends NestedFieldComparator {
Lowest(FieldComparator wrappedComparator, Filter parentFilter, Filter childFilter, int spareSlot) {
@ -298,14 +147,14 @@ abstract class NestedFieldComparator extends FieldComparator {
@Override
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
return compareBottomMissing(wrappedComparator);
}
// We need to copy the lowest value from all nested docs into slot.
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
return compareBottomMissing(wrappedComparator);
}
// We only need to emit a single cmp value for any matching nested doc
@ -333,6 +182,7 @@ abstract class NestedFieldComparator extends FieldComparator {
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
copyMissing(wrappedComparator, slot);
return;
}
@ -340,6 +190,7 @@ abstract class NestedFieldComparator extends FieldComparator {
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
copyMissing(wrappedComparator, slot);
return;
}
wrappedComparator.copy(spareSlot, nestedDoc);
@ -357,42 +208,6 @@ abstract class NestedFieldComparator extends FieldComparator {
}
}
@Override
@SuppressWarnings("unchecked")
public int compareDocToValue(int rootDoc, Object value) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
}
// We need to copy the lowest value from all nested docs into slot.
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
}
// We only need to emit a single cmp value for any matching nested doc
int cmp = wrappedComparator.compareBottom(nestedDoc);
if (cmp > 0) {
return cmp;
}
while (true) {
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return cmp;
}
int cmp1 = wrappedComparator.compareDocToValue(nestedDoc, value);
if (cmp1 > 0) {
return cmp1;
} else {
if (cmp1 == 0) {
cmp = 0;
}
}
}
}
}
final static class Highest extends NestedFieldComparator {
@ -404,13 +219,13 @@ abstract class NestedFieldComparator extends FieldComparator {
@Override
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
return compareBottomMissing(wrappedComparator);
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
return compareBottomMissing(wrappedComparator);
}
int cmp = wrappedComparator.compareBottom(nestedDoc);
@ -437,12 +252,14 @@ abstract class NestedFieldComparator extends FieldComparator {
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
copyMissing(wrappedComparator, slot);
return;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
copyMissing(wrappedComparator, slot);
return;
}
wrappedComparator.copy(spareSlot, nestedDoc);
@ -460,9 +277,80 @@ abstract class NestedFieldComparator extends FieldComparator {
}
}
}
final static class Sum extends NestedFieldComparator {
NumberComparatorBase wrappedComparator;
Sum(NumberComparatorBase wrappedComparator, Filter rootDocumentsFilter, Filter innerDocumentsFilter, int spareSlot) {
super(wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, spareSlot);
this.wrappedComparator = wrappedComparator;
}
@Override
@SuppressWarnings("unchecked")
public int compareDocToValue(int rootDoc, Object value) throws IOException {
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return compareBottomMissing(wrappedComparator);
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return compareBottomMissing(wrappedComparator);
}
wrappedComparator.copy(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
}
return compare(bottomSlot, spareSlot);
}
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
copyMissing(wrappedComparator, slot);
return;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
copyMissing(wrappedComparator, slot);
return;
}
wrappedComparator.copy(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
}
}
@Override
public FieldComparator setNextReader(AtomicReaderContext context) throws IOException {
super.setNextReader(context);
wrappedComparator = (NumberComparatorBase) super.wrappedComparator;
return this;
}
}
final static class Avg extends NestedFieldComparator {
NumberComparatorBase wrappedComparator;
Avg(NumberComparatorBase wrappedComparator, Filter rootDocumentsFilter, Filter innerDocumentsFilter, int spareSlot) {
super(wrappedComparator, rootDocumentsFilter, innerDocumentsFilter, spareSlot);
this.wrappedComparator = wrappedComparator;
}
@Override
public int compareBottom(int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return 0;
}
@ -470,30 +358,65 @@ abstract class NestedFieldComparator extends FieldComparator {
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return 0;
return compareBottomMissing(wrappedComparator);
}
int cmp = wrappedComparator.compareBottom(nestedDoc);
if (cmp < 0) {
return cmp;
}
while (true) {
int counter = 1;
wrappedComparator.copy(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(spareSlot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
return cmp;
}
int cmp1 = wrappedComparator.compareDocToValue(nestedDoc, value);
if (cmp1 < 0) {
return cmp1;
} else {
if (cmp1 == 0) {
cmp = 0;
}
}
counter++;
}
wrappedComparator.divide(spareSlot, counter);
return compare(bottomSlot, spareSlot);
}
@Override
public void copy(int slot, int rootDoc) throws IOException {
if (rootDoc == 0 || rootDocuments == null || innerDocuments == null) {
return;
}
int prevRootDoc = rootDocuments.prevSetBit(rootDoc - 1);
int nestedDoc = innerDocuments.nextSetBit(prevRootDoc + 1);
if (nestedDoc >= rootDoc || nestedDoc == -1) {
copyMissing(wrappedComparator, slot);
return;
}
int counter = 1;
wrappedComparator.copy(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
while (nestedDoc > prevRootDoc && nestedDoc < rootDoc) {
wrappedComparator.add(slot, nestedDoc);
nestedDoc = innerDocuments.nextSetBit(nestedDoc + 1);
counter++;
}
wrappedComparator.divide(slot, counter);
}
@Override
public FieldComparator setNextReader(AtomicReaderContext context) throws IOException {
super.setNextReader(context);
wrappedComparator = (NumberComparatorBase) super.wrappedComparator;
return this;
}
}
static final void copyMissing(FieldComparator comparator, int slot) {
if (comparator instanceof NumberComparatorBase) {
((NumberComparatorBase) comparator).missing(slot);
}
}
static final int compareBottomMissing(FieldComparator comparator) {
if (comparator instanceof NumberComparatorBase) {
return ((NumberComparatorBase) comparator).compareBottomMissing();
} else {
return 0;
}
}
}

View File

@ -682,6 +682,96 @@ public class SimpleNestedTests extends AbstractNodesTests {
assertThat(searchResponse.getHits().hits()[2].sortValues()[0].toString(), equalTo("2"));
}
@Test
public void testSimpleNestedSorting_withNestedFilterMissing() throws Exception {
client.admin().indices().prepareDelete().execute().actionGet();
client.admin().indices().prepareCreate("test")
.setSettings(settingsBuilder()
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 0)
.put("index.referesh_interval", -1)
.build()
)
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("nested1")
.field("type", "nested")
.endObject()
.endObject().endObject().endObject())
.execute().actionGet();
client.admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
client.prepareIndex("test", "type1", "1").setSource(jsonBuilder().startObject()
.field("field1", 1)
.startArray("nested1")
.startObject()
.field("field1", 5)
.field("field2", true)
.endObject()
.startObject()
.field("field1", 4)
.field("field2", true)
.endObject()
.endArray()
.endObject()).execute().actionGet();
client.prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject()
.field("field1", 2)
.startArray("nested1")
.startObject()
.field("field1", 1)
.field("field2", true)
.endObject()
.startObject()
.field("field1", 2)
.field("field2", true)
.endObject()
.endArray()
.endObject()).execute().actionGet();
// Doc with missing nested docs if nested filter is used
client.admin().indices().prepareRefresh().execute().actionGet();
client.prepareIndex("test", "type1", "3").setSource(jsonBuilder().startObject()
.field("field1", 3)
.startArray("nested1")
.startObject()
.field("field1", 3)
.field("field2", false)
.endObject()
.startObject()
.field("field1", 4)
.field("field2", false)
.endObject()
.endArray()
.endObject()).execute().actionGet();
client.admin().indices().prepareRefresh().execute().actionGet();
SearchResponse searchResponse = client.prepareSearch("test")
.setTypes("type1")
.setQuery(QueryBuilders.matchAllQuery())
.addSort(SortBuilders.fieldSort("nested1.field1").setNestedFilter(termFilter("nested1.field2", true)).missing(10).order(SortOrder.ASC))
.execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(3l));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("2"));
assertThat(searchResponse.getHits().hits()[0].sortValues()[0].toString(), equalTo("1"));
assertThat(searchResponse.getHits().hits()[1].id(), equalTo("1"));
assertThat(searchResponse.getHits().hits()[1].sortValues()[0].toString(), equalTo("4"));
assertThat(searchResponse.getHits().hits()[2].id(), equalTo("3"));
assertThat(searchResponse.getHits().hits()[2].sortValues()[0].toString(), equalTo("10"));
searchResponse = client.prepareSearch("test")
.setTypes("type1")
.setQuery(QueryBuilders.matchAllQuery())
.addSort(SortBuilders.fieldSort("nested1.field1").setNestedFilter(termFilter("nested1.field2", true)).missing(10).order(SortOrder.DESC))
.execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(3l));
assertThat(searchResponse.getHits().hits()[0].id(), equalTo("3"));
assertThat(searchResponse.getHits().hits()[0].sortValues()[0].toString(), equalTo("10"));
assertThat(searchResponse.getHits().hits()[1].id(), equalTo("1"));
assertThat(searchResponse.getHits().hits()[1].sortValues()[0].toString(), equalTo("5"));
assertThat(searchResponse.getHits().hits()[2].id(), equalTo("2"));
assertThat(searchResponse.getHits().hits()[2].sortValues()[0].toString(), equalTo("2"));
}
@Test
public void testSortNestedWithNestedFilter() throws Exception {
client.admin().indices().prepareDelete().execute().actionGet();

View File

@ -28,7 +28,6 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
import org.elasticsearch.common.lucene.search.AndFilter;
import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.TermFilter;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
@ -40,7 +39,6 @@ import org.testng.annotations.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
@ -148,6 +146,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
document.add(createField("field1", 5, Field.Store.NO));
docs.add(document);
writer.addDocuments(docs);
writer.commit();
docs.clear();
document = new Document();
@ -167,12 +166,14 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
document.add(createField("field1", 6, Field.Store.NO));
docs.add(document);
writer.addDocuments(docs);
writer.commit();
// This doc will not be included, because it doesn't have nested docs
document = new Document();
document.add(new StringField("__type", "parent", Field.Store.NO));
document.add(createField("field1", 7, Field.Store.NO));
writer.addDocument(document);
writer.commit();
docs.clear();
document = new Document();
@ -207,7 +208,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
SortMode sortMode = SortMode.SUM;
IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(writer, false));
IndexFieldData.XFieldComparatorSource innerFieldComparator = createInnerFieldComparator("field2", sortMode);
IndexFieldData.XFieldComparatorSource innerFieldComparator = createInnerFieldComparator("field2", sortMode, null);
Filter parentFilter = new TermFilter(new Term("__type", "parent"));
Filter childFilter = new NotFilter(parentFilter);
NestedFieldComparatorSource nestedComparatorSource = new NestedFieldComparatorSource(sortMode, innerFieldComparator, parentFilter, childFilter);
@ -243,7 +244,7 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
assertThat(topDocs.scoreDocs[4].doc, equalTo(3));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(9));
childFilter = new AndFilter(Arrays.asList(new NotFilter(parentFilter), new TermFilter(new Term("filter_1", "T"))));
childFilter = new TermFilter(new Term("filter_1", "T"));
nestedComparatorSource = new NestedFieldComparatorSource(sortMode, innerFieldComparator, parentFilter, childFilter);
query = new ToParentBlockJoinQuery(
new XFilteredQuery(new MatchAllDocsQuery(), childFilter),
@ -280,6 +281,40 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
assertThat(topDocs.scoreDocs[4].doc, equalTo(3));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(9));
innerFieldComparator = createInnerFieldComparator("field2", sortMode, 127);
nestedComparatorSource = new NestedFieldComparatorSource(sortMode, innerFieldComparator, parentFilter, childFilter);
sort = new Sort(new SortField("field2", nestedComparatorSource, true));
topDocs = searcher.search(new TermQuery(new Term("__type", "parent")), 5, sort);
assertThat(topDocs.totalHits, equalTo(8));
assertThat(topDocs.scoreDocs.length, equalTo(5));
assertThat(topDocs.scoreDocs[0].doc, equalTo(19));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(127));
assertThat(topDocs.scoreDocs[1].doc, equalTo(24));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(127));
assertThat(topDocs.scoreDocs[2].doc, equalTo(23));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(12));
assertThat(topDocs.scoreDocs[3].doc, equalTo(3));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(9));
assertThat(topDocs.scoreDocs[4].doc, equalTo(7));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(8));
innerFieldComparator = createInnerFieldComparator("field2", sortMode, -127);
nestedComparatorSource = new NestedFieldComparatorSource(sortMode, innerFieldComparator, parentFilter, childFilter);
sort = new Sort(new SortField("field2", nestedComparatorSource));
topDocs = searcher.search(new TermQuery(new Term("__type", "parent")), 5, sort);
assertThat(topDocs.totalHits, equalTo(8));
assertThat(topDocs.scoreDocs.length, equalTo(5));
assertThat(topDocs.scoreDocs[0].doc, equalTo(19));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(-127));
assertThat(topDocs.scoreDocs[1].doc, equalTo(24));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(-127));
assertThat(topDocs.scoreDocs[2].doc, equalTo(15));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3));
assertThat(topDocs.scoreDocs[3].doc, equalTo(28));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3));
assertThat(topDocs.scoreDocs[4].doc, equalTo(11));
assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(7));
// Moved to method, because floating point based XFieldComparatorSource have different outcome for SortMode avg,
// than integral number based implementations...
assertAvgScoreMode(parentFilter, searcher, innerFieldComparator);
@ -309,6 +344,6 @@ public abstract class AbstractNumberNestedSortingTests extends AbstractFieldData
protected abstract IndexableField createField(String name, int value, Field.Store store);
protected abstract IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode);
protected abstract IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue);
}

View File

@ -38,9 +38,9 @@ public class ByteNestedSortingTests extends AbstractNumberNestedSortingTests {
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
ByteArrayIndexFieldData fieldData = getForField(fieldName);
return new ByteValuesComparatorSource(fieldData, null, sortMode);
return new ByteValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override

View File

@ -49,9 +49,9 @@ public class DoubleNestedSortingTests extends AbstractNumberNestedSortingTests {
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
DoubleArrayIndexFieldData fieldData = getForField(fieldName);
return new DoubleValuesComparatorSource(fieldData, null, sortMode);
return new DoubleValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override

View File

@ -49,9 +49,9 @@ public class FloatNestedSortingTests extends AbstractNumberNestedSortingTests {
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
FloatArrayIndexFieldData fieldData = getForField(fieldName);
return new FloatValuesComparatorSource(fieldData, null, sortMode);
return new FloatValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override

View File

@ -38,9 +38,9 @@ public class IntegerNestedSortingTests extends AbstractNumberNestedSortingTests
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
IntArrayIndexFieldData fieldData = getForField(fieldName);
return new IntValuesComparatorSource(fieldData, null, sortMode);
return new IntValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override

View File

@ -38,9 +38,9 @@ public class LongNestedSortingTests extends AbstractNumberNestedSortingTests {
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
LongArrayIndexFieldData fieldData = getForField(fieldName);
return new LongValuesComparatorSource(fieldData, null, sortMode);
return new LongValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override

View File

@ -38,9 +38,9 @@ public class ShortNestedSortingTests extends AbstractNumberNestedSortingTests {
}
@Override
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode) {
protected IndexFieldData.XFieldComparatorSource createInnerFieldComparator(String fieldName, SortMode sortMode, Object missingValue) {
ShortArrayIndexFieldData fieldData = getForField(fieldName);
return new ShortValuesComparatorSource(fieldData, null, sortMode);
return new ShortValuesComparatorSource(fieldData, missingValue, sortMode);
}
@Override