private Object randomOfType(SortField.Type type) { switch (type) { case CUSTOM: throw new UnsupportedOperationException(); case DOC: return between(0, IndexWriter.MAX_DOCS); case DOUBLE: return randomDouble(); case FLOAT: return randomFloat(); case INT: return randomInt(); case LONG: return randomLong(); case REWRITEABLE: throw new UnsupportedOperationException(); case SCORE: return randomFloat(); case STRING: return new BytesRef(randomAsciiOfLength(5)); case STRING_VAL: return new BytesRef(randomAsciiOfLength(5)); default: throw new UnsupportedOperationException("Unkown SortField.Type: " + type); } }
@Override protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[2].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(3)); }
protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher, IndexFieldData.XFieldComparatorSource innerFieldComparator) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[2].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(3)); }
protected void assertAvgScoreMode(Query parentFilter, IndexSearcher searcher) throws IOException { MultiValueMode sortMode = MultiValueMode.AVG; Query childFilter = Queries.not(parentFilter); XFieldComparatorSource nestedComparatorSource = createFieldComparator("field2", sortMode, -127, createNested(searcher, parentFilter, childFilter)); Query query = new ToParentBlockJoinQuery(new ConstantScoreQuery(childFilter), new QueryBitSetProducer(parentFilter), ScoreMode.None); Sort sort = new Sort(new SortField("field2", nestedComparatorSource)); TopDocs topDocs = searcher.search(query, 5, sort); assertThat(topDocs.totalHits, equalTo(7)); assertThat(topDocs.scoreDocs.length, equalTo(5)); assertThat(topDocs.scoreDocs[0].doc, equalTo(11)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[0]).fields[0]).intValue(), equalTo(2)); assertThat(topDocs.scoreDocs[1].doc, equalTo(3)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[1]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[2].doc, equalTo(7)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[2]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[3].doc, equalTo(15)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[3]).fields[0]).intValue(), equalTo(3)); assertThat(topDocs.scoreDocs[4].doc, equalTo(19)); assertThat(((Number) ((FieldDoc) topDocs.scoreDocs[4]).fields[0]).intValue(), equalTo(4)); }
public void testSortValues() throws Exception { Directory dir = new RAMDirectory(); IndexWriter indexWriter = new IndexWriter(dir, new IndexWriterConfig(Lucene.STANDARD_ANALYZER)); for (int i = 0; i < 10; i++) { Document document = new Document(); String text = new String(new char[]{(char) (97 + i), (char) (97 + i)}); document.add(new TextField("str", text, Field.Store.YES)); document.add(new SortedDocValuesField("str", new BytesRef(text))); indexWriter.addDocument(document); } IndexReader reader = SlowCompositeReaderWrapper.wrap(DirectoryReader.open(indexWriter)); IndexSearcher searcher = new IndexSearcher(reader); TopFieldDocs docs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("str", SortField.Type.STRING))); for (int i = 0; i < 10; i++) { FieldDoc fieldDoc = (FieldDoc) docs.scoreDocs[i]; assertThat((BytesRef) fieldDoc.fields[0], equalTo(new BytesRef(new String(new char[]{(char) (97 + i), (char) (97 + i)})))); } }
/** Calculates the missing Values as in {@link org.elasticsearch.index.fielddata.IndexFieldData} * The results in the {@link org.apache.lucene.search.ScoreDoc} contains this missingValues instead of nulls. Because we * need nulls in the result, it's necessary to check if a value is a missingValue. */ public static Object missingValue(boolean reverseFlag, Boolean nullFirst, SortField.Type type) { boolean min = reverseFlag ^ (nullFirst != null ? nullFirst : reverseFlag); switch (type) { case INT: case LONG: return min ? Long.MIN_VALUE : Long.MAX_VALUE; case FLOAT: return min ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; case DOUBLE: return min ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; case STRING: case STRING_VAL: return min ? null : MAX_TERM; default: throw new UnsupportedOperationException("Unsupported reduced type: " + type); } }
@Nullable public static Sort generateLuceneSort(CollectorContext context, OrderBy orderBy, CollectInputSymbolVisitor<?> inputSymbolVisitor) { if (orderBy.orderBySymbols().isEmpty()) { return null; } SortSymbolVisitor sortSymbolVisitor = new SortSymbolVisitor(inputSymbolVisitor); SortField[] sortFields = sortSymbolVisitor.generateSortFields( orderBy.orderBySymbols(), context, orderBy.reverseFlags(), orderBy.nullsFirst() ); return new Sort(sortFields); }
@Override public void run() { int i = 0; while (i < 10000) { try { if (data.size() <= i) { sleep(1); continue; } final String key = "key" + i; final String val = "value" + i; final List<Document> documents = index.searchForDocuments(new TermQuery(new Term(key, val)), 10, new Sort(new SortField(key, SortField.Type.STRING))); if (documents.size() != 1) { throw new RuntimeException("Invalid number of matching documents for " + key + ", found " + documents); } ++i; } catch (IOException ioe) { error = ioe; break; } catch (InterruptedException e) { } catch (AlreadyClosedException ace) { error = ace; break; } } }
@Override public ScoreDoc[] prefixSearch(String keywords) throws IOException { if (StringUtils.isEmpty(keywords) || keywords.length() > appConfig.getKeywordMaxLength()) { logger.error("empty keywords or over-length! {}", keywords); return null; } Sort sort = new Sort(new SortField("downloadRank", SortField.INT, true)); Term nameFldTerm = new Term(fieldName, keywords); PrefixQuery nameFldQuery = new PrefixQuery(nameFldTerm); NumericRangeQuery<Integer> catalogQuery = NumericRangeQuery.newIntRange("catalog", (int) EnumCatalog.SOFT.getCatalog(), (int) EnumCatalog.GAME.getCatalog(), true, true); BooleanQuery booleanQuery = new BooleanQuery(); booleanQuery.add(catalogQuery, Occur.MUST); booleanQuery.add(nameFldQuery, Occur.MUST); TopDocs topDocs = quickTipsSearcher.search(booleanQuery, appConfig.getQuickTipsNum() * 2, sort); ScoreDoc[] docs = topDocs.scoreDocs; return docs; }
@Override public MergePolicy getInstance(Map<String, String> params) throws IOException { String field = params.get(SORT_FIELD); SortField.Type sortFieldType = SortField.Type.DOC; if (params.containsKey(SORT_FIELD_TYPE)) { sortFieldType = SortField.Type.valueOf(params.get(SORT_FIELD_TYPE).toUpperCase()); } if (sortFieldType == SortField.Type.DOC) { throw new IOException( "Relying on internal lucene DocIDs is not guaranteed to work, this is only an implementation detail."); } boolean desc = true; if (params.containsKey(SORT_DESC)) { try { desc = Boolean.valueOf(params.get(SORT_DESC)); } catch (Exception e) { desc = true; } } SortField sortField = new SortField(field, sortFieldType, desc); Sort sort = new Sort(sortField); return new SortingMergePolicyDecorator(new TieredMergePolicy(), sort); }
/** * Returns a Lucene {@link SortField} for sorting documents/rows according * to the partition key. * * @return a sort field for sorting by partition key */ public SortField sortField() { return new SortField(FIELD_NAME, new FieldComparatorSource() { @Override public FieldComparator<?> newComparator(String field, int hits, int sort, boolean reversed) throws IOException { return new FieldComparator.TermValComparator(hits, field, false) { @Override public int compareValues(BytesRef val1, BytesRef val2) { ByteBuffer bb1 = ByteBufferUtils.byteBuffer(val1); ByteBuffer bb2 = ByteBufferUtils.byteBuffer(val2); return ByteBufferUtil.compareUnsigned(bb1, bb2); } }; } }); }
@Override @SuppressWarnings("unchecked") public List<PostPO> searchByTag(Paging paigng, String tag) { FullTextSession fullTextSession = Search.getFullTextSession(super.session()); SearchFactory sf = fullTextSession.getSearchFactory(); QueryBuilder qb = sf.buildQueryBuilder().forEntity(PostPO.class).get(); org.apache.lucene.search.Query luceneQuery = qb.phrase().onField("tags").sentence(tag).createQuery(); FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery); query.setFirstResult(paigng.getFirstResult()); query.setMaxResults(paigng.getMaxResults()); Sort sort = new Sort(new SortField("id", SortField.Type.LONG, true)); query.setSort(sort); paigng.setTotalCount(query.getResultSize()); return query.list(); }
private String getGroupByField(List<VcfFile> files, String groupBy) throws IOException { IndexSortField sortField = IndexSortField.getByName(groupBy); if (sortField == null) { VcfFilterInfo info = vcfManager.getFiltersInfo( files.stream().map(BaseEntity::getId).collect(Collectors.toList())); InfoItem infoItem = info.getInfoItemMap().get(groupBy); Assert.notNull(infoItem, "Unknown sort field: " + groupBy); if (infoItem.getType() == VCFHeaderLineType.Integer || infoItem.getType() == VCFHeaderLineType.Float) { return FeatureIndexFields.getGroupName(infoItem.getName().toLowerCase()); } else { return infoItem.getName().toLowerCase(); } } else { if (sortField.getType() == SortField.Type.INT || sortField.getType() == SortField.Type.FLOAT) { return sortField.getField().getGroupName(); } else { return sortField.getField().fieldName; } } }
/** * Comes from Sorting of Solr * * Returns a {@link SortField} for a string field. * If nullLast and nullFirst are both false, then default lucene string sorting is used where * null strings sort first in an ascending sort, and last in a descending sort. * * @param fieldName the name of the field to sort on * @param reverse true for a reverse (desc) sort * @param nullLast true if null should come last, regardless of sort order * @param nullFirst true if null should come first, regardless of sort order * @return SortField */ public static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) { if (nullFirst && nullLast) { throw new IllegalArgumentException("Cannot specify missing values as both first and last"); } SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse); // 4 cases: // missingFirst / forward: default lucene behavior // missingFirst / reverse: set sortMissingLast // missingLast / forward: set sortMissingLast // missingLast / reverse: default lucene behavior if (nullFirst && reverse) { sortField.setMissingValue(SortField.STRING_LAST); } else if (nullLast && !reverse) { sortField.setMissingValue(SortField.STRING_LAST); } return sortField; }
public static SortField getLongSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) { if (nullFirst && nullLast) { throw new IllegalArgumentException("Cannot specify missing values as both first and last"); } SortField sortField = new SortField(fieldName, SortField.Type.LONG, reverse); // 4 cases: // missingFirst / forward: default lucene behavior // missingFirst / reverse: set sortMissingLast // missingLast / forward: set sortMissingLast // missingLast / reverse: default lucene behavior if (nullFirst && reverse) { sortField.setMissingValue(Long.MAX_VALUE); } else if (nullLast && !reverse) { sortField.setMissingValue(Long.MAX_VALUE); } return sortField; }
public List<String> extractCategories() { FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager( em ); QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( Categories.class ).get(); org.apache.lucene.search.Query query = queryBuilder.all().createQuery(); FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery( query , Categories.class ); fullTextQuery.setProjection( FullTextQuery.ID , "category" ); Sort sort = new Sort( new SortField( "category" , SortField.STRING ) ); fullTextQuery.setSort( sort ); //fullTextQuery.initializeObjectsWith(ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID); List<String> results = fullTextQuery.getResultList(); return results; }
/** Uses variables with $ */ public void testDollarVariable() throws Exception { Expression expr = JavascriptCompiler.compile("$0+$score"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("$0", SortField.Type.SCORE)); bindings.add(new SortField("$score", SortField.Type.SCORE)); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = 2*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
private void doTestLotsOfBindings(int n) throws Exception { SimpleBindings bindings = new SimpleBindings(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { if (i > 0) { sb.append("+"); } sb.append("x" + i); bindings.add(new SortField("x" + i, SortField.Type.SCORE)); } Expression expr = JavascriptCompiler.compile(sb.toString()); Sort sort = new Sort(expr.getSortField(bindings, true)); Query query = new TermQuery(new Term("body", "contents")); TopFieldDocs td = searcher.search(query, null, 3, sort, true, true); for (int i = 0; i < 3; i++) { FieldDoc d = (FieldDoc) td.scoreDocs[i]; float expected = n*d.score; float actual = ((Double)d.fields[0]).floatValue(); assertEquals(expected, actual, CheckHits.explainToleranceDelta(expected, actual)); } }
public void testRangeScorer() throws Exception { Expression expr = JavascriptCompiler.compile("2*popularity"); SimpleBindings bindings = new SimpleBindings(); bindings.add(new SortField("popularity", SortField.Type.LONG)); ValueSource vs = expr.getValueSource(bindings); assertEquals(1, reader.leaves().size()); AtomicReaderContext leaf = reader.leaves().get(0); FunctionValues values = vs.getValues(new HashMap<String,Object>(), leaf); // everything ValueSourceScorer scorer = values.getRangeScorer(leaf.reader(), "4", "40", true, true); assertEquals(-1, scorer.docID()); assertEquals(0, scorer.nextDoc()); assertEquals(1, scorer.nextDoc()); assertEquals(2, scorer.nextDoc()); assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.nextDoc()); // just the first doc scorer = values.getRangeScorer(leaf.reader(), "4", "40", false, false); assertEquals(-1, scorer.docID()); assertEquals(0, scorer.nextDoc()); assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.nextDoc()); }
void assertQuery(Query query, Filter filter) throws Exception { for (int i = 0; i < 10; i++) { boolean reversed = random().nextBoolean(); SortField fields[] = new SortField[] { new SortField("int", SortField.Type.INT, reversed), new SortField("long", SortField.Type.LONG, reversed), new SortField("float", SortField.Type.FLOAT, reversed), new SortField("double", SortField.Type.DOUBLE, reversed), new SortField("intdocvalues", SortField.Type.INT, reversed), new SortField("floatdocvalues", SortField.Type.FLOAT, reversed), new SortField("score", SortField.Type.SCORE) }; Collections.shuffle(Arrays.asList(fields), random()); int numSorts = TestUtil.nextInt(random(), 1, fields.length); assertQuery(query, filter, new Sort(Arrays.copyOfRange(fields, 0, numSorts))); } }
private Sort getRandomSort(boolean scoreOnly) { final List<SortField> sortFields = new ArrayList<>(); if (random().nextInt(7) == 2 || scoreOnly) { sortFields.add(SortField.FIELD_SCORE); } else { if (random().nextBoolean()) { if (random().nextBoolean()) { sortFields.add(new SortField("sort1", SortField.Type.STRING, random().nextBoolean())); } else { sortFields.add(new SortField("sort2", SortField.Type.STRING, random().nextBoolean())); } } else if (random().nextBoolean()) { sortFields.add(new SortField("sort1", SortField.Type.STRING, random().nextBoolean())); sortFields.add(new SortField("sort2", SortField.Type.STRING, random().nextBoolean())); } } // Break ties: if (random().nextBoolean() && !scoreOnly) { sortFields.add(new SortField("sort3", SortField.Type.STRING)); } else if (!scoreOnly) { sortFields.add(new SortField("id", SortField.Type.INT)); } return new Sort(sortFields.toArray(new SortField[sortFields.size()])); }
public List<Products> extractPromotionalProducts() { FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager( em ); org.apache.lucene.search.Query query = NumericRangeQuery.newDoubleRange( "old_price" , 0.0d , 1000d , false , true ); FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery( query , Products.class ); Sort sort = new Sort( new SortField( "price" , SortField.DOUBLE ) ); fullTextQuery.setSort( sort ); //fullTextQuery.initializeObjectsWith(ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID); List results = fullTextQuery.getResultList(); return results; }
/** * Returns a QueryContext with sorting added to it. * * @param key The key to sort on. * @param additionalKeys Any additional keys to sort on. * @return A QueryContext with sorting added to it. */ public QueryContext sort( String key, String... additionalKeys ) { SortField firstSortField = new SortedSetSortField( key, false ); if ( additionalKeys.length == 0 ) { return sort( new Sort( firstSortField ) ); } SortField[] sortFields = new SortField[1+additionalKeys.length]; sortFields[0] = firstSortField; for ( int i = 0; i < additionalKeys.length; i++ ) { sortFields[1+i] = new SortedSetSortField( additionalKeys[i], false ); } return sort( new Sort( sortFields ) ); }
public void testSingleton() throws Exception { Directory dir = newDirectory(); RandomIndexWriter writer = new RandomIndexWriter(random(), dir); Document doc = new Document(); doc.add(new SortedNumericDocValuesField("value", 5)); doc.add(newStringField("id", "2", Field.Store.YES)); writer.addDocument(doc); doc = new Document(); doc.add(new SortedNumericDocValuesField("value", 3)); doc.add(newStringField("id", "1", Field.Store.YES)); writer.addDocument(doc); IndexReader ir = writer.getReader(); writer.close(); IndexSearcher searcher = newSearcher(ir); Sort sort = new Sort(new SortedNumericSortField("value", SortField.Type.INT)); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); assertEquals(2, td.totalHits); // 3 comes before 5 assertEquals("1", searcher.doc(td.scoreDocs[0].doc).get("id")); assertEquals("2", searcher.doc(td.scoreDocs[1].doc).get("id")); ir.close(); dir.close(); }
Comparator<ShardDoc> comparatorFieldComparator(SortField sortField) { final FieldComparator fieldComparator; try { fieldComparator = sortField.getComparator(0, 0); } catch (IOException e) { throw new RuntimeException("Unable to get FieldComparator for sortField " + sortField); } return new ShardComparator(sortField) { // Since the PriorityQueue keeps the biggest elements by default, // we need to reverse the field compare ordering so that the // smallest elements are kept instead of the largest... hence // the negative sign. @Override public int compare(final ShardDoc o1, final ShardDoc o2) { //noinspection unchecked return -fieldComparator.compareValues(sortVal(o1), sortVal(o2)); } }; }
public Map<Integer , List<Products>> extractProducts( String id , int page ) { FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager( em ); QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( Products.class ).get(); org.apache.lucene.search.Query query = queryBuilder.keyword().onField( "category.id" ).matching( id ).createQuery(); FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery( query , Products.class ); Sort sort = new Sort( new SortField( "price" , SortField.DOUBLE ) ); fullTextQuery.setSort( sort ); //fullTextQuery.initializeObjectsWith(ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID); fullTextQuery.setFirstResult( page * 3 ); fullTextQuery.setMaxResults( 3 ); List<Products> results = fullTextQuery.getResultList(); Map<Integer , List<Products>> results_and_total = new HashMap<Integer , List<Products>>(); results_and_total.put( fullTextQuery.getResultSize() , results ); return results_and_total; }
@Test public void shouldReturnDocValuesInGivenOrder() throws Exception { // given DocValuesCollector collector = new DocValuesCollector( false ); IndexReaderStub readerStub = indexReaderWithMaxDocs( 42 ); // when collector.doSetNextReader( readerStub.getContext() ); collector.collect( 1 ); collector.collect( 2 ); // then Sort byIdDescending = new Sort( new SortField( "id", SortField.Type.LONG, true ) ); PrimitiveLongIterator valuesIterator = collector.getSortedValuesIterator( "id", byIdDescending ); assertEquals( 2, valuesIterator.next() ); assertEquals( 1, valuesIterator.next() ); assertFalse( valuesIterator.hasNext() ); }
public static FieldDoc buildFieldDoc(SortAndFormats sort, Object[] values) { if (sort == null || sort.sort.getSort() == null || sort.sort.getSort().length == 0) { throw new IllegalArgumentException("Sort must contain at least one field."); } SortField[] sortFields = sort.sort.getSort(); if (sortFields.length != values.length) { throw new IllegalArgumentException( SEARCH_AFTER.getPreferredName() + " has " + values.length + " value(s) but sort has " + sort.sort.getSort().length + "."); } Object[] fieldValues = new Object[sortFields.length]; for (int i = 0; i < sortFields.length; i++) { SortField sortField = sortFields[i]; DocValueFormat format = sort.formats[i]; if (values[i] != null) { fieldValues[i] = convertValueFromSortField(values[i], sortField, format); } else { fieldValues[i] = null; } } /* * We set the doc id to Integer.MAX_VALUE in order to make sure that the search starts "after" the first document that is equal to * the field values. */ return new FieldDoc(Integer.MAX_VALUE, 0, fieldValues); }
private static Object convertValueFromSortField(Object value, SortField sortField, DocValueFormat format) { if (sortField.getComparatorSource() instanceof IndexFieldData.XFieldComparatorSource) { IndexFieldData.XFieldComparatorSource cmpSource = (IndexFieldData.XFieldComparatorSource) sortField.getComparatorSource(); return convertValueFromSortType(sortField.getField(), cmpSource.reducedType(), value, format); } return convertValueFromSortType(sortField.getField(), sortField.getType(), value, format); }
@Override public SortFieldAndFormat build(QueryShardContext context) throws IOException { if (DOC_FIELD_NAME.equals(fieldName)) { if (order == SortOrder.DESC) { return SORT_DOC_REVERSE; } else { return SORT_DOC; } } else { MappedFieldType fieldType = context.fieldMapper(fieldName); if (fieldType == null) { if (unmappedType != null) { fieldType = context.getMapperService().unmappedFieldType(unmappedType); } else { throw new QueryShardException(context, "No mapping found for [" + fieldName + "] in order to sort on"); } } MultiValueMode localSortMode = null; if (sortMode != null) { localSortMode = MultiValueMode.fromString(sortMode.toString()); } boolean reverse = (order == SortOrder.DESC); if (localSortMode == null) { localSortMode = reverse ? MultiValueMode.MAX : MultiValueMode.MIN; } final Nested nested = resolveNested(context, nestedPath, nestedFilter); IndexFieldData<?> fieldData = context.getForField(fieldType); if (fieldData instanceof IndexNumericFieldData == false && (sortMode == SortMode.SUM || sortMode == SortMode.AVG || sortMode == SortMode.MEDIAN)) { throw new QueryShardException(context, "we only support AVG, MEDIAN and SUM on number based fields"); } IndexFieldData.XFieldComparatorSource fieldComparatorSource = fieldData .comparatorSource(missing, localSortMode, nested); SortField field = new SortField(fieldType.name(), fieldComparatorSource, reverse); return new SortFieldAndFormat(field, fieldType.docValueFormat(null, null)); } }
public static Optional<SortAndFormats> buildSort(List<SortBuilder<?>> sortBuilders, QueryShardContext context) throws IOException { List<SortField> sortFields = new ArrayList<>(sortBuilders.size()); List<DocValueFormat> sortFormats = new ArrayList<>(sortBuilders.size()); for (SortBuilder<?> builder : sortBuilders) { SortFieldAndFormat sf = builder.build(context); sortFields.add(sf.field); sortFormats.add(sf.format); } if (!sortFields.isEmpty()) { // optimize if we just sort on score non reversed, we don't really // need sorting boolean sort; if (sortFields.size() > 1) { sort = true; } else { SortField sortField = sortFields.get(0); if (sortField.getType() == SortField.Type.SCORE && !sortField.getReverse()) { sort = false; } else { sort = true; } } if (sort) { return Optional.of(new SortAndFormats( new Sort(sortFields.toArray(new SortField[sortFields.size()])), sortFormats.toArray(new DocValueFormat[sortFormats.size()]))); } } return Optional.empty(); }
@Override public Object missingValue(boolean reversed) { if (sortMissingFirst(missingValue) || sortMissingLast(missingValue)) { if (sortMissingLast(missingValue) ^ reversed) { return SortField.STRING_LAST; } else { return SortField.STRING_FIRST; } } // otherwise we fill missing values ourselves return null; }
private static void writeMissingValue(StreamOutput out, Object missingValue) throws IOException { if (missingValue == SortField.STRING_FIRST) { out.writeByte((byte) 1); } else if (missingValue == SortField.STRING_LAST) { out.writeByte((byte) 2); } else { out.writeByte((byte) 0); out.writeGenericValue(missingValue); } }
private static Object readMissingValue(StreamInput in) throws IOException { final byte id = in.readByte(); switch (id) { case 0: return in.readGenericValue(); case 1: return SortField.STRING_FIRST; case 2: return SortField.STRING_LAST; default: throw new IOException("Unknown missing value id: " + id); } }
public static SortField readSortField(StreamInput in) throws IOException { String field = null; if (in.readBoolean()) { field = in.readString(); } SortField.Type sortType = readSortType(in); Object missingValue = readMissingValue(in); boolean reverse = in.readBoolean(); SortField sortField = new SortField(field, sortType, reverse); if (missingValue != null) { sortField.setMissingValue(missingValue); } return sortField; }
public static void writeSortField(StreamOutput out, SortField sortField) throws IOException { if (sortField.getClass() == GEO_DISTANCE_SORT_TYPE_CLASS) { // for geo sorting, we replace the SortField with a SortField that assumes a double field. // this works since the SortField is only used for merging top docs SortField newSortField = new SortField(sortField.getField(), SortField.Type.DOUBLE); newSortField.setMissingValue(sortField.getMissingValue()); sortField = newSortField; } if (sortField.getClass() != SortField.class) { throw new IllegalArgumentException("Cannot serialize SortField impl [" + sortField + "]"); } if (sortField.getField() == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeString(sortField.getField()); } if (sortField.getComparatorSource() != null) { IndexFieldData.XFieldComparatorSource comparatorSource = (IndexFieldData.XFieldComparatorSource) sortField.getComparatorSource(); writeSortType(out, comparatorSource.reducedType()); writeMissingValue(out, comparatorSource.missingValue(sortField.getReverse())); } else { writeSortType(out, sortField.getType()); writeMissingValue(out, sortField.getMissingValue()); } out.writeBoolean(sortField.getReverse()); }
public void testEmptyNumericSegment() throws Exception { final Directory dir = newDirectory(); final RandomIndexWriter w = new RandomIndexWriter(random(), dir); Document doc = new Document(); doc.add(new NumericDocValuesField("group", 0)); w.addDocument(doc); doc.clear(); doc.add(new NumericDocValuesField("group", 1)); w.addDocument(doc); w.commit(); doc.clear(); doc.add(new NumericDocValuesField("group", 10)); w.addDocument(doc); w.commit(); doc.clear(); doc.add(new NumericDocValuesField("category", 0)); w.addDocument(doc); w.commit(); final IndexReader reader = w.getReader(); final IndexSearcher searcher = newSearcher(reader); SortField sortField = new SortField("group", SortField.Type.LONG); sortField.setMissingValue(Long.MAX_VALUE); Sort sort = new Sort(sortField); final CollapsingTopDocsCollector collapsingCollector = CollapsingTopDocsCollector.createNumeric("group", sort, 10, false); searcher.search(new MatchAllDocsQuery(), collapsingCollector); CollapseTopFieldDocs collapseTopFieldDocs = collapsingCollector.getTopDocs(); assertEquals(4, collapseTopFieldDocs.scoreDocs.length); assertEquals(4, collapseTopFieldDocs.collapseValues.length); assertEquals(0L, collapseTopFieldDocs.collapseValues[0]); assertEquals(1L, collapseTopFieldDocs.collapseValues[1]); assertEquals(10L, collapseTopFieldDocs.collapseValues[2]); assertNull(collapseTopFieldDocs.collapseValues[3]); w.close(); reader.close(); dir.close(); }
public void testEmptySortedSegment() throws Exception { final Directory dir = newDirectory(); final RandomIndexWriter w = new RandomIndexWriter(random(), dir); Document doc = new Document(); doc.add(new SortedDocValuesField("group", new BytesRef("0"))); w.addDocument(doc); doc.clear(); doc.add(new SortedDocValuesField("group", new BytesRef("1"))); w.addDocument(doc); w.commit(); doc.clear(); doc.add(new SortedDocValuesField("group", new BytesRef("10"))); w.addDocument(doc); w.commit(); doc.clear(); doc.add(new NumericDocValuesField("category", 0)); w.addDocument(doc); w.commit(); final IndexReader reader = w.getReader(); final IndexSearcher searcher = newSearcher(reader); Sort sort = new Sort(new SortField("group", SortField.Type.STRING_VAL)); final CollapsingTopDocsCollector collapsingCollector = CollapsingTopDocsCollector.createKeyword("group", sort, 10, false); searcher.search(new MatchAllDocsQuery(), collapsingCollector); CollapseTopFieldDocs collapseTopFieldDocs = collapsingCollector.getTopDocs(); assertEquals(4, collapseTopFieldDocs.scoreDocs.length); assertEquals(4, collapseTopFieldDocs.collapseValues.length); assertNull(collapseTopFieldDocs.collapseValues[0]); assertEquals(new BytesRef("0"), collapseTopFieldDocs.collapseValues[1]); assertEquals(new BytesRef("1"), collapseTopFieldDocs.collapseValues[2]); assertEquals(new BytesRef("10"), collapseTopFieldDocs.collapseValues[3]); w.close(); reader.close(); dir.close(); }
private SortField[] randomSortFields() { SortField[] sortFields = new SortField[between(1, 5)]; Set<String> usedSortFields = new HashSet<>(); for (int i = 0; i < sortFields.length; i++) { String sortField = randomValueOtherThanMany(usedSortFields::contains, () -> randomAsciiOfLength(5)); usedSortFields.add(sortField); SortField.Type type = randomValueOtherThanMany(t -> t == SortField.Type.CUSTOM || t == SortField.Type.REWRITEABLE, () -> randomFrom(SortField.Type.values())); sortFields[i] = new SortField(sortField, type); } return sortFields; }