lucene是一個很強大的搜索工具,最近公司項目上用到,結合JAVA1234所講,對多條件查詢做出總結
先描述一下我的多條件需求,如果和您的類似,繼續往下看。
1、我的Lucene搜索會在很多地方使用,使用時的條件各不相同
2、只建立一份索引
使用的工具包(點我下載):
一、創建索引文件
import java.io.File; import java.io.FileReader; import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.wltea.analyzer.lucene.IKAnalyzer; public class LuceneCreateIndex { private IndexWriter indexWriter = null; public LuceneCreateIndex( String indexDir ) throws Exception { // IKAnalyzer 有獨特之處,同時支持多種語言的分詞 Analyzer analyzer = new IKAnalyzer(); Directory directory = FSDirectory.open( Paths.get( indexDir ) ); IndexWriterConfig indexWriterConfig = new IndexWriterConfig( analyzer ); indexWriter = new IndexWriter( directory, indexWriterConfig ); } /** * 將測試數據文件寫入索引 * @param dataDir * @throws Exception */ public void createIndex( String dataDir ) throws Exception { File[] files = new File( dataDir ).listFiles(); for ( File file : files ) { Document document = getDocument( file ); indexWriter.addDocument( document ); System.out.println( "已建立索引文件:" + file.getCanonicalPath() ); } indexWriter.close(); } public Document getDocument( File file ) throws Exception { Document document = new Document(); document.add( new TextField( "contents", new FileReader( file ) ) ); document.add( new TextField( "fileName", file.getName(), Field.Store.YES ) ); document.add( new TextField( "fullPath", file.getCanonicalPath(), Field.Store.YES ) ); return document; } public static void main( String[] args ) { String indexDir = "D:\\luceneTest";// 索引文件生成目錄 String dataDir = "D:\\luceneTest\\data";// 測試數據目錄(測試數據見下圖) try { new LuceneCreateIndex( indexDir ).createIndex( dataDir ); } catch ( Exception e ) { e.printStackTrace(); } } }
運行生成索引文件;測試數據如下
2、測試搜索效果
import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.wltea.analyzer.lucene.IKAnalyzer; public class LuceneTestSearch { /** * 單條件查詢 * @param indexDir * @param q * @throws Exception */ public static void search( String indexDir, String q ) throws Exception { Directory directory = FSDirectory.open( Paths.get( indexDir ) ); IndexReader indexReader = DirectoryReader.open( directory ); IndexSearcher indexSearcher = new IndexSearcher( indexReader ); Analyzer analyzer = new IKAnalyzer(); // 搜索目標是 contents QueryParser parser = new QueryParser( "contents", analyzer ); // 傳入關鍵字,進行分析 Query query = parser.parse( q ); // 分頁,這里取前十個 TopDocs topDocs = indexSearcher.search( query, 10 ); for ( ScoreDoc scoreDoc : topDocs.scoreDocs ) { // 獲取搜索結果 Document document = indexSearcher.doc( scoreDoc.doc ); System.out.println( document.get( "fullPath" ) ); } indexReader.close(); } /** * 多條件查詢 * @param indexDir * @param q * @throws Exception */ public static void searchBooleanQuery( String indexDir, String q ) throws Exception { Directory directory = FSDirectory.open( Paths.get( indexDir ) ); IndexReader indexReader = DirectoryReader.open( directory ); IndexSearcher indexSearcher = new IndexSearcher( indexReader ); Analyzer analyzer = new IKAnalyzer(); // 多條件必備神器 BooleanQuery.Builder builder = new BooleanQuery.Builder(); // 實際使用中一般是多目標搜索(根據 姓名、性別、年齡、學校等等), //QueryParser parser = new MultiFieldQueryParser( new String[]{"contents","fullPath"}, analyzer ); // 條件一 QueryParser parser = new QueryParser( "contents", analyzer ); Query query = parser.parse( q ); // contents必須含有條件一 builder.add( query, Occur.MUST ); // 條件二 QueryParser parser1 = new QueryParser( "fileName", analyzer ); Query query1 = parser1.parse( "b c" ); // fileName必須不能是 b 和 c builder.add( query1, Occur.MUST_NOT ); TopDocs topDocs = indexSearcher.search( builder.build(), 10 ); for ( ScoreDoc scoreDoc : topDocs.scoreDocs ) { Document document = indexSearcher.doc( scoreDoc.doc ); System.out.println( document.get( "fullPath" ) ); } indexReader.close(); } public static void main( String[] args ) { String indexDir = "D:\\luceneTest"; String q = "1"; try { // 搜索contents含有1的文件信息 System.out.println( "單條件查詢:" ); search( indexDir, q ); // 搜索contents含有1 但是除開文件b 和 c System.out.println( "多條件查詢:" ); searchBooleanQuery( indexDir, q ); } catch ( Exception e ) { e.printStackTrace(); } } }
搜索結果如下
單條件查詢:
D:\luceneTest\data\d.txt
D:\luceneTest\data\b.txt
D:\luceneTest\data\c.txt
D:\luceneTest\data\a.txt
多條件查詢:
D:\luceneTest\data\d.txt
D:\luceneTest\data\a.txt
關於更多lucene的學習,歡迎和博主交流