下面列出了怎么用org.apache.lucene.search.SortField的API类实例代码及写法,或者点击链接到github查看源代码。
@SuppressWarnings("unchecked")
@Override
public List<User> search(String searchTerm, Integer limit, Integer offset) {
FullTextQuery query = getSearchQuery(searchTerm);
query.setSort(new Sort(new SortField(Binding.user().userName().getPath(), SortField.Type.STRING)));
if (offset != null) {
query.setFirstResult(offset);
}
if (limit != null) {
query.setMaxResults(limit);
}
return (List<User>) query.getResultList();
}
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()]));
}
@Override
public List<Artifact> searchAutocomplete(String searchPattern, Integer limit, Integer offset) throws ServiceException {
String[] searchFields = new String[] {
Binding.artifact().artifactId().getPath(),
Binding.artifact().group().groupId().getPath()
};
QueryBuilder queryBuilder = Search.getFullTextEntityManager(getEntityManager()).getSearchFactory().buildQueryBuilder()
.forEntity(Artifact.class).get();
Query luceneQuery = queryBuilder.keyword().onField(Binding.artifact().deprecationStatus().getPath()).matching(ArtifactDeprecationStatus.NORMAL).createQuery();
List<SortField> sortFields = ImmutableList.<SortField>builder()
.add(new SortField(Binding.artifact().group().getPath() + '.' + ArtifactGroup.GROUP_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.add(new SortField(Artifact.ARTIFACT_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.build();
Sort sort = new Sort(sortFields.toArray(new SortField[sortFields.size()]));
return hibernateSearchService.searchAutocomplete(getObjectClass(), searchFields, searchPattern, luceneQuery, limit, offset, sort);
}
public void testFiltersOutOfOrder1() {
// the hashcode should be the same even when the list
// of filters is in a different order
Sort sort = new Sort(new SortField("test", SortField.Type.INT));
BooleanQuery.Builder query = new BooleanQuery.Builder();
query.add(new TermQuery(new Term("test", "field")), Occur.MUST);
List<Query> filters = Arrays.<Query>asList(new TermQuery(new Term("test", "field")),
new TermQuery(new Term("test2", "field2")));
QueryResultKey qrk1 = new QueryResultKey(query.build() , filters, sort, 1);
List<Query> filters2 = Arrays.<Query>asList(new TermQuery(new Term("test2", "field2")),
new TermQuery(new Term("test", "field")));
QueryResultKey qrk2 = new QueryResultKey(query.build() , filters2, sort, 1);
assertKeyEquals(qrk1, qrk2);
}
public void testIllegalIndexSortChange2() throws Exception {
Directory dir1 = newDirectory();
IndexWriterConfig iwc1 = newIndexWriterConfig(new MockAnalyzer(random()));
iwc1.setIndexSort(new Sort(new SortField("foo", SortField.Type.INT)));
RandomIndexWriter w1 = new RandomIndexWriter(random(), dir1, iwc1);
w1.addDocument(new Document());
w1.commit();
w1.addDocument(new Document());
w1.commit();
// so the index sort is in fact burned into the index:
w1.forceMerge(1);
w1.close();
Directory dir2 = newDirectory();
IndexWriterConfig iwc2 = newIndexWriterConfig(new MockAnalyzer(random()));
iwc2.setIndexSort(new Sort(new SortField("foo", SortField.Type.STRING)));
RandomIndexWriter w2 = new RandomIndexWriter(random(), dir2, iwc2);
IndexReader r1 = DirectoryReader.open(dir1);
String message = expectThrows(IllegalArgumentException.class, () -> {
w2.addIndexes((SegmentReader) getOnlyLeafReader(r1));
}).getMessage();
assertEquals("cannot change index sort from <int: \"foo\"> to <string: \"foo\">", message);
IOUtils.close(r1, dir1, w2, dir2);
}
@SuppressWarnings("unchecked")
@Override
public List<Artifact> searchByName(String searchTerm, ArtifactDeprecationStatus deprecation, Integer limit, Integer offset) {
FullTextQuery query = getSearchByNameQuery(searchTerm, deprecation);
// Sort
List<SortField> sortFields = ImmutableList.<SortField>builder()
.add(new SortField(Binding.artifact().group().getPath() + '.' + ArtifactGroup.GROUP_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.add(new SortField(Artifact.ARTIFACT_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.build();
query.setSort(new Sort(sortFields.toArray(new SortField[sortFields.size()])));
if (offset != null) {
query.setFirstResult(offset);
}
if (limit != null) {
query.setMaxResults(limit);
}
return (List<Artifact>) query.getResultList();
}
@SuppressWarnings({"unchecked","rawtypes"})
private Comparable<?>[] fillFields(GroupDoc d, Sort sort) {
final SortField[] sortFields = sort.getSort();
final Comparable<?>[] fields = new Comparable[sortFields.length];
for(int fieldIDX=0;fieldIDX<sortFields.length;fieldIDX++) {
final Comparable<?> c;
final SortField sf = sortFields[fieldIDX];
if (sf.getType() == SortField.Type.SCORE) {
c = d.score;
} else if (sf.getField().equals("sort1")) {
c = d.sort1;
} else if (sf.getField().equals("sort2")) {
c = d.sort2;
} else {
assertEquals("id", sf.getField());
c = d.id;
}
fields[fieldIDX] = c;
}
return fields;
}
/** Tests sorting a single document with scores */
public void testSortOneDocumentWithScores() throws Exception {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
Document doc = new Document();
doc.add(newStringField("value", "foo", Field.Store.YES));
writer.addDocument(doc);
IndexReader ir = UninvertingReader.wrap(writer.getReader(),
Collections.singletonMap("value", Type.SORTED));
writer.close();
IndexSearcher searcher = newSearcher(ir);
Sort sort = new Sort(new SortField("value", SortField.Type.STRING));
TopDocs expected = searcher.search(new TermQuery(new Term("value", "foo")), 10);
assertEquals(1, expected.totalHits.value);
TopDocs actual = searcher.search(new TermQuery(new Term("value", "foo")), 10, sort, true);
assertEquals(expected.totalHits.value, actual.totalHits.value);
assertEquals(expected.scoreDocs[0].score, actual.scoreDocs[0].score, 0F);
TestUtil.checkReader(ir);
ir.close();
dir.close();
}
public void testSortingMPSolrIndexConfigCreation() throws Exception {
final String expectedFieldName = "timestamp_i_dvo";
final SortField.Type expectedFieldType = SortField.Type.INT;
final boolean expectedFieldSortDescending = true;
SolrConfig solrConfig = new SolrConfig(instanceDir, solrConfigFileNameSortingMergePolicyFactory);
SolrIndexConfig solrIndexConfig = new SolrIndexConfig(solrConfig, null, null);
assertNotNull(solrIndexConfig);
IndexSchema indexSchema = IndexSchemaFactory.buildIndexSchema(schemaFileName, solrConfig);
h.getCore().setLatestSchema(indexSchema);
IndexWriterConfig iwc = solrIndexConfig.toIndexWriterConfig(h.getCore());
final MergePolicy mergePolicy = iwc.getMergePolicy();
assertNotNull("null mergePolicy", mergePolicy);
assertTrue("mergePolicy ("+mergePolicy+") is not a SortingMergePolicy", mergePolicy instanceof SortingMergePolicy);
final SortingMergePolicy sortingMergePolicy = (SortingMergePolicy) mergePolicy;
final Sort expected = new Sort(new SortField(expectedFieldName, expectedFieldType, expectedFieldSortDescending));
final Sort actual = sortingMergePolicy.getSort();
assertEquals("SortingMergePolicy.getSort", expected, actual);
}
Comparator<ShardDoc> getCachedComparator(SortField sortField, IndexSearcher searcher) {
SortField.Type type = sortField.getType();
if (type == SortField.Type.SCORE) {
return (o1, o2) -> {
final float f1 = o1.score;
final float f2 = o2.score;
if (f1 < f2)
return -1;
if (f1 > f2)
return 1;
return 0;
};
} else if (type == SortField.Type.REWRITEABLE) {
try {
sortField = sortField.rewrite(searcher);
} catch (IOException e) {
throw new SolrException(SERVER_ERROR, "Exception rewriting sort field " + sortField, e);
}
}
return comparatorFieldComparator(sortField);
}
@Override
public boolean equals(Object o) {
if (o==this) return true;
if (!(o instanceof QueryResultKey)) return false;
QueryResultKey other = (QueryResultKey)o;
// fast check of the whole hash code... most hash tables will only use
// some of the bits, so if this is a hash collision, it's still likely
// that the full cached hash code will be different.
if (this.hc != other.hc) return false;
// check for the thing most likely to be different (and the fastest things)
// first.
if (this.sfields.length != other.sfields.length) return false;
if (!this.query.equals(other.query)) return false;
if (!unorderedCompare(this.filters, other.filters)) return false;
if (this.minExactCount != other.minExactCount) return false;
for (int i=0; i<sfields.length; i++) {
SortField sf1 = this.sfields[i];
SortField sf2 = other.sfields[i];
if (!sf1.equals(sf2)) return false;
}
return true;
}
@Test
public void givenSortFieldWhenSortedThenCorrect() {
InMemoryLuceneIndex inMemoryLuceneIndex = new InMemoryLuceneIndex(new RAMDirectory(), new StandardAnalyzer());
inMemoryLuceneIndex.indexDocument("Ganges", "River in India");
inMemoryLuceneIndex.indexDocument("Mekong", "This river flows in south Asia");
inMemoryLuceneIndex.indexDocument("Amazon", "Rain forest river");
inMemoryLuceneIndex.indexDocument("Rhine", "Belongs to Europe");
inMemoryLuceneIndex.indexDocument("Nile", "Longest River");
Term term = new Term("body", "river");
Query query = new WildcardQuery(term);
SortField sortField = new SortField("title", SortField.Type.STRING_VAL, false);
Sort sortByTitle = new Sort(sortField);
List<Document> documents = inMemoryLuceneIndex.searchIndex(query, sortByTitle);
Assert.assertEquals(4, documents.size());
Assert.assertEquals("Amazon", documents.get(0).getField("title").stringValue());
}
private static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) {
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;
}
private void setSortSpec(ResponseBuilder rb, boolean forceElevation, ElevationComparatorSource comparator) {
// if the sort is 'score desc' use a custom sorting method to
// insert documents in their proper place
SortSpec sortSpec = rb.getSortSpec();
if (sortSpec.getSort() == null) {
sortSpec.setSortAndFields(
new Sort(
new SortField("_elevate_", comparator, true),
new SortField(null, SortField.Type.SCORE, false)),
Arrays.asList(new SchemaField[2]));
} else {
// Check if the sort is based on score
SortSpec modSortSpec = this.modifySortSpec(sortSpec, forceElevation, comparator);
if (null != modSortSpec) {
rb.setSortSpec(modSortSpec);
}
}
}
private DoubleValuesSource fromSortField(SortField field) {
switch(field.getType()) {
case INT:
return DoubleValuesSource.fromIntField(field.getField());
case LONG:
return DoubleValuesSource.fromLongField(field.getField());
case FLOAT:
return DoubleValuesSource.fromFloatField(field.getField());
case DOUBLE:
return DoubleValuesSource.fromDoubleField(field.getField());
case SCORE:
return DoubleValuesSource.SCORES;
default:
throw new UnsupportedOperationException();
}
}
@RequestMapping(value = "/recentrequest", method = RequestMethod.GET)
public String currentlog(Model model) {
Sort sort = new Sort(new SortField("time", SortField.Type.DOUBLE, true));
Query query = new MatchAllDocsQuery();
ResponseJson result = indexHelper.searchByQuery(DateTimeHelper.getCurrentTime(), query, 0, 500, sort);
model.addAttribute("resultlist", result.getResult());
return "recentrequest";
}
private SortField customSortField(String name,
final Symbol symbol,
final SortSymbolContext context) {
InputFactory.Context<? extends LuceneCollectorExpression<?>> inputContext = docInputFactory.getCtx(context.txnCtx);
final Input<?> input = inputContext.add(symbol);
final List<? extends LuceneCollectorExpression<?>> expressions = inputContext.expressions();
final CollectorContext collectorContext = context.context;
final boolean nullFirst = context.nullFirst;
return new SortField(name, new FieldComparatorSource() {
@Override
public FieldComparator<?> newComparator(String fieldName, int numHits, int sortPos, boolean reversed) {
for (int i = 0; i < expressions.size(); i++) {
expressions.get(i).startCollect(collectorContext);
}
@SuppressWarnings("unchecked")
DataType<Object> dataType = (DataType<Object>) symbol.valueType();
Object nullSentinel = NullSentinelValues.nullSentinel(
dataType,
NullValueOrder.fromFlag(nullFirst),
reversed);
return new InputFieldComparator(
numHits,
expressions,
input,
// for non `null` sentinel values, the nullSentinel already implies reverse+nullsFirst logic
// for `null` sentinels we need to have a comparator that can deal with that
nullSentinel == null
? nullFirst ^ reversed ? Comparator.nullsFirst(dataType) : Comparator.nullsLast(dataType)
: dataType,
nullSentinel
);
}
}, context.reverseFlag);
}
/** Wraps the provided {@link SortedNumericDocValues} in order to only select
* one value per parent among its {@code children} using the configured
* {@code selection} type. */
public static NumericDocValues wrap(SortedNumericDocValues sortedNumerics, Type selection, BitSet parents, DocIdSetIterator children) {
NumericDocValues values;
switch (selection) {
case MIN:
values = SortedNumericSelector.wrap(sortedNumerics, SortedNumericSelector.Type.MIN, SortField.Type.LONG);
break;
case MAX:
values = SortedNumericSelector.wrap(sortedNumerics, SortedNumericSelector.Type.MAX, SortField.Type.LONG);
break;
default:
throw new AssertionError();
}
return wrap(values, selection, parents, children);
}
public void testBasic() throws Exception {
Directory dir = newDirectory();
RandomIndexWriter iw = new RandomIndexWriter(random(), dir);
Document doc = new Document();
Field field = newField("field", "", StringField.TYPE_STORED);
CollationDocValuesField collationField = new CollationDocValuesField("collated", Collator.getInstance(Locale.ENGLISH));
doc.add(field);
doc.add(collationField);
field.setStringValue("ABC");
collationField.setStringValue("ABC");
iw.addDocument(doc);
field.setStringValue("abc");
collationField.setStringValue("abc");
iw.addDocument(doc);
IndexReader ir = iw.getReader();
iw.close();
IndexSearcher is = newSearcher(ir);
SortField sortField = new SortField("collated", SortField.Type.STRING);
TopDocs td = is.search(new MatchAllDocsQuery(), 5, new Sort(sortField));
assertEquals("abc", ir.document(td.scoreDocs[0].doc).get("field"));
assertEquals("ABC", ir.document(td.scoreDocs[1].doc).get("field"));
ir.close();
dir.close();
}
/**
* Suggest similar words (optionally restricted to a field of an index).
*
* <p>As the Lucene similarity that is used to fetch the most relevant n-grammed terms
* is not the same as the edit distance strategy used to calculate the best
* matching autocomplete word from the hits that Lucene found, one usually has
* to retrieve a couple of numSug's in order to get the true best match.
*
* <p>I.e. if numSug == 1, don't count on that suggestion being the best one.
* Thus, you should set this value to <b>at least</b> 5 for a good suggestion.
*
* @param word the word you want a auto complete done on
* @param numSug the number of suggested words
* @param ir the indexReader of the user index (can be null see field param)
* @param field the field of the user index: if field is not null, the suggested
* words are restricted to the words present in this field.
* @throws IOException if the underlying index throws an {@link IOException}
* @throws AlreadyClosedException if the Autocompleter is already closed
* @return List<String> the sorted list of the suggest words with these 2 criteria:
* first criteria: the edit distance, second criteria (only if restricted mode): the popularity
* of the suggest words in the field of the user index
*/
public String[] suggestSimilar(String word, int numSug) throws IOException {
// obtainSearcher calls ensureOpen
final IndexSearcher indexSearcher = obtainSearcher();
try{
BooleanQuery query = new BooleanQuery();
List<String[]> grams = formGrams(word);
String key;
for (String[] gramArray : grams) {
for (int i = 0; i < gramArray.length; i++) {
key = "start" + gramArray[i].length(); // form key
add(query, key, gramArray[i]);
}
}
int maxHits = 2 * numSug;
//First sort on similarity, then on popularity (based on frequency in the source index)
SortField[] sortFields = {SortField.FIELD_SCORE, new SortField(F_FREQ, SortField.INT, true)};
ScoreDoc[] hits = indexSearcher.search(query, maxHits, new Sort(sortFields)).scoreDocs;
//indexSearcher.search(query, null, maxHits).scoreDocs;
int stop = Math.min(hits.length, maxHits);
String[] toReturn = new String[stop];
for (int i = 0; i < stop; i++) {
toReturn[i] = indexSearcher.doc(hits[i].doc).get(F_WORD); // get orig word
}
return toReturn;
} finally {
releaseSearcher(indexSearcher);
}
}
/**
* Returns a mapping from the old document ID to its new location in the
* sorted index. Implementations can use the auxiliary
* {@link #sort(int, IndexSorter.DocComparator)} to compute the old-to-new permutation
* given a list of documents and their corresponding values.
* <p>
* A return value of <code>null</code> is allowed and means that
* <code>reader</code> is already sorted.
* <p>
* <b>NOTE:</b> deleted documents are expected to appear in the mapping as
* well, they will however be marked as deleted in the sorted view.
*/
DocMap sort(LeafReader reader) throws IOException {
SortField[] fields = sort.getSort();
final IndexSorter.DocComparator[] comparators = new IndexSorter.DocComparator[fields.length];
for (int i = 0; i < fields.length; i++) {
IndexSorter sorter = fields[i].getIndexSorter();
if (sorter == null) {
throw new IllegalArgumentException("Cannot use sortfield + " + fields[i] + " to sort indexes");
}
comparators[i] = sorter.getDocComparator(reader, reader.maxDoc());
}
return sort(reader.maxDoc(), comparators);
}
/** Returns whether collection can be early-terminated if it sorts with the
* provided {@link Sort} and if segments are merged with the provided
* {@link Sort}. */
public static boolean canEarlyTerminate(Sort searchSort, Sort mergePolicySort) {
final SortField[] fields1 = searchSort.getSort();
final SortField[] fields2 = mergePolicySort.getSort();
// early termination is possible if fields1 is a prefix of fields2
if (fields1.length > fields2.length) {
return false;
}
return Arrays.asList(fields1).equals(Arrays.asList(fields2).subList(0, fields1.length));
}
/**
* Utility usable by subclasses when they want to get basic String sorting
* using common checks.
* @see SchemaField#checkSortability
* @see #getSortedSetSortField
* @see #getSortField
*/
protected SortField getStringSort(SchemaField field, boolean reverse) {
if (field.multiValued()) {
MultiValueSelector selector = field.type.getDefaultMultiValueSelectorForSort(field, reverse);
if (null != selector) {
return getSortedSetSortField(field, selector.getSortedSetSelectorType(),
reverse, SortField.STRING_FIRST, SortField.STRING_LAST);
}
}
// else...
// either single valued, or don't support implicit multi selector
// (in which case let getSortField() give the error)
return getSortField(field, SortField.Type.STRING, reverse, SortField.STRING_FIRST, SortField.STRING_LAST);
}
private long runQuery(IndexSearcher s, Query q) throws Exception {
s.search(q, 10);
long hitCount = s.search(q, 10, new Sort(new SortField("titleDV", SortField.Type.STRING))).totalHits.value;
final Sort dvSort = new Sort(new SortField("titleDV", SortField.Type.STRING));
long hitCount2 = s.search(q, 10, dvSort).totalHits.value;
assertEquals(hitCount, hitCount2);
return hitCount;
}
/**
* Set the {@link Sort} order to use for all (flushed and merged) segments.
*/
public IndexWriterConfig setIndexSort(Sort sort) {
for (SortField sortField : sort.getSort()) {
if (sortField.getIndexSorter() == null) {
throw new IllegalArgumentException("Cannot sort index with sort field " + sortField);
}
}
this.indexSort = sort;
this.indexSortFields = Arrays.stream(sort.getSort()).map(SortField::getField).collect(Collectors.toSet());
return this;
}
public void testTieBreak() throws Exception {
Directory dir = newDirectory();
IndexWriterConfig iwc = newIndexWriterConfig(new MockAnalyzer(random()));
iwc.setIndexSort(new Sort(new SortField("foo", SortField.Type.STRING)));
iwc.setMergePolicy(newLogMergePolicy());
IndexWriter w = new IndexWriter(dir, iwc);
for(int id=0;id<1000;id++) {
Document doc = new Document();
doc.add(new StoredField("id", id));
String value;
if (id < 500) {
value = "bar2";
} else {
value = "bar1";
}
doc.add(new SortedDocValuesField("foo", new BytesRef(value)));
w.addDocument(doc);
if (id == 500) {
w.commit();
}
}
w.forceMerge(1);
DirectoryReader r = DirectoryReader.open(w);
for(int docID=0;docID<1000;docID++) {
int expectedID;
if (docID < 500) {
expectedID = 500 + docID;
} else {
expectedID = docID - 500;
}
assertEquals(expectedID, r.document(docID).getField("id").numericValue().intValue());
}
IOUtils.close(r, w, dir);
}
Geo3DPointSortField(final String field, final PlanetModel planetModel, final GeoDistanceShape distanceShape) {
super(field, SortField.Type.CUSTOM);
if (field == null) {
throw new IllegalArgumentException("field must not be null");
}
if (distanceShape == null) {
throw new IllegalArgumentException("distanceShape must not be null");
}
this.distanceShape = distanceShape;
this.planetModel = planetModel;
setMissingValue(Double.POSITIVE_INFINITY);
}
@Override
public SortField getSortField(SchemaField field, boolean top) {
final SortField result = getNumericSort(field, NumberType.INTEGER, top);
if (null == result.getMissingValue()) {
// special case 'enum' default behavior: assume missing values are "below" all enum values
result.setMissingValue(Integer.MIN_VALUE);
}
return result;
}
@SuppressWarnings( "unchecked" )
public F clearSorting( ) {
this.sortFields = "";
this.sortDirections = "";
sortObj = new Sort( );
sortObj.setSort( new SortField[0] );
updateSorting = updateParamMap = true;
return ( F )this;
}
private static Sort randomSort() {
// at least 2
int numFields = TestUtil.nextInt(random(), 2, 4);
SortField[] sortFields = new SortField[numFields];
for(int i=0;i<numFields-1;i++) {
SortField sortField = randomIndexSortField();
sortFields[i] = sortField;
}
// tie-break by id:
sortFields[numFields-1] = new SortField("id", SortField.Type.INT);
return new Sort(sortFields);
}