Lucene - 排序



  • 简述

    在本章中,我们将研究 Lucene 默认给出搜索结果的排序顺序,或者可以根据需要对其进行操作。
  • 按相关性排序

    这是 Lucene 使用的默认排序模式。Lucene 通过顶部最相关的命中提供结果。
    
    private void sortUsingRelevance(String searchQuery)
       throws IOException, ParseException {
       searcher = new Searcher(indexDir);
       long startTime = System.currentTimeMillis();
       
       //create a term to search file name
       Term term = new Term(LuceneConstants.FILE_NAME, searchQuery);
       //create the term query object
       Query query = new FuzzyQuery(term);
       searcher.setDefaultFieldSortScoring(true, false);
       //do the search
       TopDocs hits = searcher.search(query,Sort.RELEVANCE);
       long endTime = System.currentTimeMillis();
       System.out.println(hits.totalHits +
          " documents found. Time :" + (endTime - startTime) + "ms");
       for(ScoreDoc scoreDoc : hits.scoreDocs) {
          Document doc = searcher.getDocument(scoreDoc);
          System.out.print("Score: "+ scoreDoc.score + " ");
          System.out.println("File: "+ doc.get(LuceneConstants.FILE_PATH));
       }
       searcher.close();
    }
    
    
  • 按索引顺序排序

    Lucene 使用这种排序模式。在这里,索引的第一个文档首先显示在搜索结果中。
    
    private void sortUsingIndex(String searchQuery)
       throws IOException, ParseException {
       searcher = new Searcher(indexDir);
       long startTime = System.currentTimeMillis();
       
       //create a term to search file name
       Term term = new Term(LuceneConstants.FILE_NAME, searchQuery);
       //create the term query object
       Query query = new FuzzyQuery(term);
       searcher.setDefaultFieldSortScoring(true, false);
       //do the search
       TopDocs hits = searcher.search(query,Sort.INDEXORDER);
       long endTime = System.currentTimeMillis();
       System.out.println(hits.totalHits +
          " documents found. Time :" + (endTime - startTime) + "ms");
       for(ScoreDoc scoreDoc : hits.scoreDocs) {
          Document doc = searcher.getDocument(scoreDoc);
          System.out.print("Score: "+ scoreDoc.score + " ");
          System.out.println("File: "+ doc.get(LuceneConstants.FILE_PATH));
       }
       searcher.close();
    }
    
    
  • 示例应用

    让我们创建一个测试 Lucene 应用程序来测试排序过程。
    描述
    1
    创建一个名称的项目LuceneFirstApplication一个包下com.jc2182.lucene作为解释Lucene的-第一个应用程序的章节。您也可以使用在Lucene - First Application章节中创建的项目来理解本章的搜索过程。
    2
    按照Lucene - First Application章节中的说明创建LuceneConstants.javaSearcher.java。保持其余文件不变。
    3
    如下所述创建LuceneTester.java
    4
    清理并构建应用程序以确保业务逻辑按照要求工作。

    LuceneConstants.java

    此类用于提供要在整个示例应用程序中使用的各种常量。
    
    package com.jc2182.lucene;
    public class LuceneConstants {
       public static final String CONTENTS = "contents";
       public static final String FILE_NAME = "filename";
       public static final String FILE_PATH = "filepath";
       public static final int MAX_SEARCH = 10;
    }
    
    

    Searcher.java

    此类用于读取对原始数据建立的索引并使用 Lucene 库搜索数据。
    
    package com.jc2182.lucene;
    import java.io.File;
    import java.io.IOException;
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.index.CorruptIndexException;
    import org.apache.lucene.queryParser.ParseException;
    import org.apache.lucene.queryParser.QueryParser;
    import org.apache.lucene.search.IndexSearcher;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.ScoreDoc;
    import org.apache.lucene.search.Sort;
    import org.apache.lucene.search.TopDocs;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.FSDirectory;
    import org.apache.lucene.util.Version;
    public class Searcher {
         
    IndexSearcher indexSearcher;
       QueryParser queryParser;
       Query query;
       public Searcher(String indexDirectoryPath) throws IOException {
          Directory indexDirectory 
             = FSDirectory.open(new File(indexDirectoryPath));
          indexSearcher = new IndexSearcher(indexDirectory);
          queryParser = new QueryParser(Version.LUCENE_36,
             LuceneConstants.CONTENTS,
             new StandardAnalyzer(Version.LUCENE_36));
       }
       public TopDocs search( String searchQuery) 
          throws IOException, ParseException {
          query = queryParser.parse(searchQuery);
          return indexSearcher.search(query, LuceneConstants.MAX_SEARCH);
       }
       public TopDocs search(Query query) 
          throws IOException, ParseException {
          return indexSearcher.search(query, LuceneConstants.MAX_SEARCH);
       }
       public TopDocs search(Query query,Sort sort) 
          throws IOException, ParseException {
          return indexSearcher.search(query, 
             LuceneConstants.MAX_SEARCH,sort);
       }
       public void setDefaultFieldSortScoring(boolean doTrackScores, 
          boolean doMaxScores) {
          indexSearcher.setDefaultFieldSortScoring(
             doTrackScores,doMaxScores);
       }
       public Document getDocument(ScoreDoc scoreDoc) 
          throws CorruptIndexException, IOException {
          return indexSearcher.doc(scoreDoc.doc);     
       }
       public void close() throws IOException {
          indexSearcher.close();
       }
    }
    
    

    LuceneTester.java

    该类用于测试Lucene库的搜索能力。
    
    package com.jc2182.lucene;
    import java.io.IOException;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.index.Term;
    import org.apache.lucene.queryParser.ParseException;
    import org.apache.lucene.search.FuzzyQuery;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.ScoreDoc;
    import org.apache.lucene.search.Sort;
    import org.apache.lucene.search.TopDocs;
    public class LuceneTester {
         
       String indexDir = "E:\\Lucene\\Index";
       String dataDir = "E:\\Lucene\\Data";
       Indexer indexer;
       Searcher searcher;
       public static void main(String[] args) {
          LuceneTester tester;
          try {
              tester = new LuceneTester();
              tester.sortUsingRelevance("cord3.txt");
              tester.sortUsingIndex("cord3.txt");
          } catch (IOException e) {
              e.printStackTrace();
          } catch (ParseException e) {
              e.printStackTrace();
          }        
       }
       private void sortUsingRelevance(String searchQuery)
          throws IOException, ParseException {
          searcher = new Searcher(indexDir);
          long startTime = System.currentTimeMillis();
          
          //create a term to search file name
          Term term = new Term(LuceneConstants.FILE_NAME, searchQuery);
          //create the term query object
          Query query = new FuzzyQuery(term);
          searcher.setDefaultFieldSortScoring(true, false);
          //do the search
          TopDocs hits = searcher.search(query,Sort.RELEVANCE);
          long endTime = System.currentTimeMillis();
          System.out.println(hits.totalHits +
             " documents found. Time :" + (endTime - startTime) + "ms");
          for(ScoreDoc scoreDoc : hits.scoreDocs) {
             Document doc = searcher.getDocument(scoreDoc);
             System.out.print("Score: "+ scoreDoc.score + " ");
             System.out.println("File: "+ doc.get(LuceneConstants.FILE_PATH));
          }
          searcher.close();
       }
       private void sortUsingIndex(String searchQuery)
          throws IOException, ParseException {
          searcher = new Searcher(indexDir);
          long startTime = System.currentTimeMillis();
          //create a term to search file name
          Term term = new Term(LuceneConstants.FILE_NAME, searchQuery);
          //create the term query object
          Query query = new FuzzyQuery(term);
          searcher.setDefaultFieldSortScoring(true, false);
          //do the search
          TopDocs hits = searcher.search(query,Sort.INDEXORDER);
          long endTime = System.currentTimeMillis();
          System.out.println(hits.totalHits +
          " documents found. Time :" + (endTime - startTime) + "ms");
          for(ScoreDoc scoreDoc : hits.scoreDocs) {
             Document doc = searcher.getDocument(scoreDoc);
             System.out.print("Score: "+ scoreDoc.score + " ");
             System.out.println("File: "+ doc.get(LuceneConstants.FILE_PATH));
          }
          searcher.close();
       }
    }
    
    
  • 数据和索引目录创建

    我们使用了从 record1.txt 到 record10.txt 的 10 个文本文件,其中包含学生的姓名和其他详细信息,并将它们放在目录中 E:\Lucene\Data. 测试数据。索引目录路径应创建为 E:\Lucene\Index。运行本章中的索引程序后Lucene - Indexing Process,您可以看到在该文件夹中创建的索引文件列表。
  • 运行程序

    完成源、原始数据、数据目录、索引目录和索引的创建后,就可以编译和运行程序了。为此,请保持LuceneTester.Java 激活文件选项卡并使用 Eclipse IDE 中提供的运行选项或使用 Ctrl + F11 编译并运行你的 LuceneTester应用。如果您的应用程序成功运行,它将在 Eclipse IDE 的控制台中打印以下消息 -
    
    10 documents found. Time :31ms
    Score: 1.3179655 File: E:\Lucene\Data\record3.txt
    Score: 0.790779 File: E:\Lucene\Data\record1.txt
    Score: 0.790779 File: E:\Lucene\Data\record2.txt
    Score: 0.790779 File: E:\Lucene\Data\record4.txt
    Score: 0.790779 File: E:\Lucene\Data\record5.txt
    Score: 0.790779 File: E:\Lucene\Data\record6.txt
    Score: 0.790779 File: E:\Lucene\Data\record7.txt
    Score: 0.790779 File: E:\Lucene\Data\record8.txt
    Score: 0.790779 File: E:\Lucene\Data\record9.txt
    Score: 0.2635932 File: E:\Lucene\Data\record10.txt
    10 documents found. Time :0ms
    Score: 0.790779 File: E:\Lucene\Data\record1.txt
    Score: 0.2635932 File: E:\Lucene\Data\record10.txt
    Score: 0.790779 File: E:\Lucene\Data\record2.txt
    Score: 1.3179655 File: E:\Lucene\Data\record3.txt
    Score: 0.790779 File: E:\Lucene\Data\record4.txt
    Score: 0.790779 File: E:\Lucene\Data\record5.txt
    Score: 0.790779 File: E:\Lucene\Data\record6.txt
    Score: 0.790779 File: E:\Lucene\Data\record7.txt
    Score: 0.790779 File: E:\Lucene\Data\record8.txt
    Score: 0.790779 File: E:\Lucene\Data\record9.txt