Lucene5多条件查询

时间:2022-12-17 05:40:57

lucene是一个很强大的搜索工具,最近公司项目上用到,结合JAVA1234所讲,对多条件查询做出总结

先描述一下我的多条件需求,如果和您的类似,继续往下看。

1、我的Lucene搜索会在很多地方使用,使用时的条件各不相同

2、只建立一份索引

使用的工具包(点我下载):

Lucene5多条件查询 

一、创建索引文件

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

运行生成索引文件;测试数据如下

Lucene5多条件查询Lucene5多条件查询 

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的学习,欢迎和博主交流