Lucene5多条件查询
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的学习,欢迎和博主交流