【问题标题】:How to sort Numeric field in Lucene 6如何在 Lucene 6 中对数字字段进行排序
【发布时间】:2017-07-05 22:32:23
【问题描述】:

我想根据数字字段对搜索结果进行排序。 在下面的示例代码中,我想根据“年龄”字段进行排序。 我从使用以下答案开始:

[How to sort IntPont or LongPoint field in Lucene 6

但它确实基于 SCORE 排序。年龄还没有上升。

[Sorting search result in Lucene based on a numeric field

我在搜索功能中将 SortField.Type.SCORE 更改为 SortField.Type.LONG。 但我明白了:

字段“年龄”的意外文档值类型 NONE(预期 = NUM​​ERIC)

这是我的代码:

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();

    }
}

正如我们所见,对 STRING 进行排序很好,但我不知道如何对我的数字 (LONG) 进行排序。

对数字字段进行排序的正确方法是什么?

谢谢

【问题讨论】:

    标签: java lucene


    【解决方案1】:

    要使用SortedNumericDocValuesField 对搜索结果进行排序,您需要使用SortedNumericSortField

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

    【讨论】:

    • 其实我也试过这个。还是有错误。只是不同:字段“年龄”的意外文档值类型 NONE(应为 [SORTED_NUMERIC, NUMERIC] 之一)
    • @moonbeam - 有理由确定你弄错了,因为我用这个修改运行了 你的代码,它工作得很好。
    • 我确实剪切粘贴了您的代码。您使用的是哪个版本的 Lucene?我正在使用 6.4.1
    • @moonbeam - 您指出的错误我希望看到您是否尝试使用SortedNumericDocValuesField 对“姓名”字段而不是“年龄”字段进行排序。会不会是这个问题?
    • 在线TopDocs docs = searcher.search(new MatchAllDocsQuery(), 100, sort);。得到:线程“main”java.lang.IllegalStateException 中的异常:字段“age”的意外文档值类型 NONE(应为 [SORTED_NUMERIC, NUMERIC] 之一)。使用正确的文档值类型重新索引。
    【解决方案2】:

    我建议你使用 ArrayList 来存储 Document 中的数据,而不是将其保存到另一个文档中,然后使用 ArrayList 的排序方法。

    请访问这些链接以供参考。

    SO - how to sort arraylist

    JAVA ArrayList sort method sample

    【讨论】:

    • 是的,可以这样做,但这意味着将整个搜索结果复制到内存中并从 Lucene 外部对其进行排序。这个想法是使用 Lucene 记录的排序容量。这个问题是想弄清楚如何使用这个 Lucene 功能对数字字段进行排序,因为我能够对字符串字段进行排序
    猜你喜欢
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 2010-10-04
    • 2017-01-26
    • 2011-06-08
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    相关资源
    最近更新 更多