简体   繁体   中英

How to sort Numeric field in Lucene 6

I want to sort my search result based on a numeric field. In the following example code, I want to sort based on the 'age' field. I start from using the answers from:

[ How to sort IntPont or LongPoint field in Lucene 6

But it does sort based SCORE. The age are still not ascending.

And

[ Sorting search result in Lucene based on a numeric field

I changed SortField.Type.SCORE to SortField.Type.LONG in the search function. But I get:

unexpected docvalues type NONE for field 'age' (expected=NUMERIC)

Here my code:

public class TestLongPointSort {


    public static void main(String[] args) throws Exception {

        String indexPath = "/tmp/testSort";
        Analyzer standardAnalyzer = new StandardAnalyzer();
        Directory indexDir = FSDirectory.open(Paths.get(indexPath));
        IndexWriterConfig iwc = new IndexWriterConfig(standardAnalyzer);

        iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

        IndexWriter masterIndex = new IndexWriter(indexDir, iwc);

        Document doc = new Document();

        String name = "bob";
        doc.add(new TextField("name", name, Field.Store.YES));
        doc.add(new SortedDocValuesField("name", new BytesRef(name)));
        doc.add(new SortedNumericDocValuesField("age", 20L));
        doc.add(new StoredField("age", 20L));
        long ts = System.currentTimeMillis();
        doc.add(new SortedNumericDocValuesField("ts", ts));
        doc.add(new StoredField("ts", ts));
        masterIndex.addDocument(doc);
        Thread.sleep(1);

        name = "max";
        doc = new Document();
        doc.add(new TextField("name", name, Field.Store.YES));
        doc.add(new SortedDocValuesField("name", new BytesRef(name)));
        doc.add(new SortedNumericDocValuesField("age", 19L));
        doc.add(new StoredField("age", 19L));
        ts = System.currentTimeMillis();
        doc.add(new SortedNumericDocValuesField("ts", ts));
        doc.add(new StoredField("ts", ts));
        masterIndex.addDocument(doc);
        Thread.sleep(1);

        name = "jim";
        doc = new Document();
        doc.add(new TextField("name", name, Field.Store.YES));
        doc.add(new SortedDocValuesField("name", new BytesRef(name)));
        doc.add(new SortedNumericDocValuesField("age", 21L));
        doc.add(new StoredField("age", 21L));
        ts = System.currentTimeMillis();
        doc.add(new SortedNumericDocValuesField("ts", ts));
        doc.add(new StoredField("ts", ts));
        masterIndex.addDocument(doc);

        masterIndex.commit();
        masterIndex.close();

        IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));
        IndexSearcher searcher = new IndexSearcher(reader);

        Analyzer analyzer = new KeywordAnalyzer();
        QueryParser queryParser = new QueryParser("message", analyzer);

        Sort sort;
        TopDocs docs;
        sort = new Sort(new SortField("name", SortField.Type.STRING));
        docs = searcher.search(new MatchAllDocsQuery(), 100, sort);
        System.out.println("Sorted by name");
        for (ScoreDoc scoreDoc : docs.scoreDocs) {
            Document doc2 = searcher.doc(scoreDoc.doc);
            System.out.println("Name:" + doc2.get("name") + " ; age:" + doc2.get("age") + " ; ts:" + doc2.get("ts"));
        }

        //docs = searcher.search(new MatchAllDocsQuery(), 100, new Sort(new SortField("age", SortField.Type.SCORE, true)));
        docs = searcher.search(new MatchAllDocsQuery(), 100, new Sort(new SortField("age", SortField.Type.LONG, true)));
        System.out.println("Sorted by age");
        for (ScoreDoc scoreDoc : docs.scoreDocs) {

            Document doc2 = searcher.doc(scoreDoc.doc);
            System.out.println("Name:" + doc2.get("name") + " ; age:" + doc2.get("age") + " ; ts:" + doc2.get("ts"));
        }

        reader.close();

    }
}

As we can see, sorting STRING is good but I didn't figure out how I can get my numbers (LONG) sorted.

What is the right way to sort Numeric fields?

Thanks

To sort search results using a SortedNumericDocValuesField , you'll need to use a SortedNumericSortField :

Sort sort = new Sort(new SortedNumericSortField("age", SortField.Type.LONG, true));
TopDocs docs = searcher.search(new MatchAllDocsQuery(), 100, sort);

I would suggest you use ArrayList to store data from Document rather than saving it to another document, then use sort methods of ArrayList.

Please visit these links for your reference.

SO - how to sort arraylist

JAVA ArrayList sort method sample

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM