Lucence
jar包
commons-io-2.4.jar
IKAnalyzer2012FF_u1.jar
junit-4.9.jar
lucene-analyzers-common-4.10.3.jar
lucene-core-4.10.3.jar
lucene-queryparser-4.10.3.jar
流程:
1、创建索引并写入索引库中
publicclassIndexSearchTest {
// 存储文档对象,文档对象还总包含域
List<Document>docs = newArrayList<>();
@Test
publicvoidIndexCreateTest() throwsIOException {
Filedir= newFile("/home/lxj/文档/参考资料/searchsource");
for(Filef:dir.listFiles()){
StringfileName= f.getName();
StringfileContext= FileUtils.readFileToString(f);
LongfileSize= FileUtils.sizeOf(f);
// 文档对象
Documentdoc= newDocument();
/*
* 第一个参数:域名
* 第二个参数:值
* 第三个参数:是否存储,Store.YES、Store.NO
*/
TextFieldnameField= newTextField("fileName",fileName,Store.YES);
TextFieldcontextField= newTextField("fileContext",fileContext,Store.YES);
TextFieldsizeField= newTextField("fileSize",fileSize.toString(),Store.YES);
doc.add(nameField);
doc.add(contextField);
doc.add(sizeField);
docs.add(doc);
}
/*
* 将文档放入磁盘,并将文档的内容进行分词
* 标准分词器,对英文很好,中文,单个字就是一个词
*/
Analyzeranalyzer= newStandardAnalyzer();
// 指定索引和文档存储目录
Directorydirectory= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// 创建写对象初始化对象
IndexWriterConfigconfig= newIndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
// 创建索引写对象
IndexWriteriWriter= newIndexWriter(directory,config);
// j将文档加入索引和文档的写对象中
for(Documentd:docs){
iWriter.addDocument(d);
}
iWriter.commit();
iWriter.close();
}
}
luke的使用
控制台模式下
输入java-jar lukeall-4.10.3.jar ,然后在path下输入索引库的位置
索引库:放索引的文件夹,自行创建。
filed:域
document:文档
term:词元,lucence中最小的单位。
2、从索引库中读取相关的值
流程:
待完善。。。。。。
@Test
publicvoidtestSearch() throwsIOException, ParseException {
// 创建与写入相同的分词器
Analyzeranalyzer= newStandardAnalyzer();
// 创建查询对象,第一个是默认搜索域,第二是分词器
QueryParserqueryParser= newQueryParser("fileContext",analyzer);
// 查询语法域名:关键词相当于sql
Queryquery = queryParser.parse("fileName:apache");
// 指定索引库目录
Directorydir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// 创建索引读取对象
IndexReaderiReader= IndexReader.open(dir);
// 创建索引的搜索对象
IndexSearchersearcher= newIndexSearcher(iReader);
// 搜索,参数:第一个是查询语句对象,第二个指定显示多少条
TopDocs topDocs= searcher.search(query,10);
// 错搜索结果获取结果集
ScoreDoc[]scoredocs= topDocs.scoreDocs;
System.out.println("=-====一共查询到+"+topDocs.totalHits+"记录=====");
for(ScoreDocsd:scoredocs){
// 获取ID
intdocId= sd.doc;
// 通过ID获取对应的文档
Documentdoc= iReader.document(docId);
// 根据域名获取对应的值
System.out.println("=====fileName:"+doc.get("fileName"));
System.out.println("=====fileSize:"+doc.get("fileSize"));
}
iReader.close();
}
3、域的详细介绍
是否分词
分词的目的是为了索引
需要分词:文件名称,文件内容
不需要分词:不需要索引的域,分词后无意义的域不需要分词,比如身份证号。
是否索引
需要搜索的域一定要索引,
索引:文件名称、文件内容、身份证号、
不需要索引的:图片地址不需要创建索引,图片地址搜索无意义。
是否存储
是否存储看个人需要,存储就是document内容存入磁盘中。如果需要马上显示存入document中查询显示速度快,如果不是马上显示出来,则不存储,额外占用磁盘,不划算。
域的各种类型:
4、中文分词
StandardAnalyzer:
单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
效果:“我”、“爱”、“中”、“国”。
CJKAnalyzer
二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。
上边两个分词器无法满足需求。
SmartChineseAnalyzer
对中文支持较好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理
使用IK_Analyzer进行分词
// 创建索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// 创建写对象配置对象
IndexWriterConfigconfig= newIndexWriterConfig(Version.LUCENE_4_10_3,newIKAnalyzer());
// 创建写对象
IndexWriteriWriter = newIndexWriter(dir, config);
扩展词库和禁用词库
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEpropertiesSYSTEM"http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IKAnalyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典
<entrykey="ext_dict">ext.dic;</entry>
-->
<!--用户可以在这里配置自己的扩展停止词字典-->
<entrykey="ext_stopwords">stopword.dic;</entry>
</properties>
5、删除
@Test
publicvoidIndexDel() throwsIOException {
// 索引库
Directorydir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// 创建写对象
IndexWriterwriter= newIndexWriter(dir,newIndexWriterConfig(Version.LUCENE_4_10_3,newIKAnalyzer()));
// 删除所有
// writer.deleteAll();
// Term就是一个词,第一个参数:域名,第二个就是词的域中含有关键词的数据
writer.deleteDocuments(newTerm("fileName","apache"));
writer.commit();
writer.close();
}
6、使用TermQuery进行查询,相比
别的不变,之前使用QueryPaser进行查询,这种方式多了一个默认的搜索域。
publicvoidTermQuery() throwsIOException {
// 索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// reader对象
IndexReaderreader= IndexReader.open(dir);
// 创建seracher对象
IndexSearchersearcher= newIndexSearcher(reader);
// 创建TermQuery对象
org.apache.lucene.search.TermQueryteQuery= neworg.apache.lucene.search.TermQuery(newTerm("fileName","java"));
// 获取搜索集
TopDocstopdocs= searcher.search(teQuery,10);
// 获取结果接
ScoreDoc[]docs= topdocs.scoreDocs;
for(ScoreDocdoc:docs){
// doc是一个文件的ID
Document document= reader.document(doc.doc);
System.out.println(document.get("fileName"));
System.out.println(document.get("fileSize"));
}
}
7、使用数字范围查询
publicvoidNumericRangeQuery()throwsIOException {
// 索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// reader对象
IndexReaderreader= IndexReader.open(dir);
// 创建seracher对象
IndexSearchersearcher= newIndexSearcher(reader);
// 使用数值范围查询
Queryquery= org.apache.lucene.search.NumericRangeQuery.newLongRange("fileSize",100L, 1000L, true,true);
// 获取搜索集
TopDocstopdocs= searcher.search(query,10);
// 获取结果接
ScoreDoc[]docs= topdocs.scoreDocs;
for(ScoreDocdoc:docs){
// doc是一个文件的ID
Document document= reader.document(doc.doc);
System.out.println(document.get("fileName"));
System.out.println(document.get("fileSize"));
}
}
8、使用BooleanQuery进行多条件查询
// 索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// reader对象
IndexReaderreader= IndexReader.open(dir);
// 创建seracher对象
IndexSearchersearcher= newIndexSearcher(reader);
// 使用数值范围查询
Queryquery= org.apache.lucene.search.NumericRangeQuery.newLongRange("fileSize",100L, 2000L, true,true);
// 创建TermQuery对象
org.apache.lucene.search.TermQueryteQuery= neworg.apache.lucene.search.TermQuery(newTerm("fileName","java"));
// 组合查询文件中包含Java,文件大小在100到1000之间的
org.apache.lucene.search.BooleanQuerybQuery= neworg.apache.lucene.search.BooleanQuery();
// Occur.MUST是并且的&o的意思should是或的意思, must_not是非的意思
bQuery.add(teQuery,Occur.MUST);
bQuery.add(query,Occur.MUST);
// 获取搜索集
TopDocstopdocs= searcher.search(bQuery,10);
// 获取结果接
ScoreDoc[]docs= topdocs.scoreDocs;
for(ScoreDocdoc:docs){
// doc是一个文件的ID
Document document= reader.document(doc.doc);
System.out.println(document.get("fileName"));
System.out.println(document.get("fileSize"));
}
}
@Test
publicvoidNumericRangeQuery() throwsIOException {
// 多个查询进行组合查询
// 索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// reader对象
IndexReaderreader= IndexReader.open(dir);
// 创建seracher对象
IndexSearchersearcher= newIndexSearcher(reader);
// 使用数值范围查询
Queryquery= org.apache.lucene.search.NumericRangeQuery.newLongRange("fileSize",100L, 2000L, true,true);
// 获取搜索集
TopDocstopdocs= searcher.search(query,10);
// 获取结果接
ScoreDoc[]docs= topdocs.scoreDocs;
for(ScoreDocdoc:docs){
// doc是一个文件的ID
Document document= reader.document(doc.doc);
System.out.println(document.get("fileName"));
System.out.println(document.get("fileSize"));
}
}
9、MutiFieldsQuery查询
使用多个域进行查询
publicvoid MultiFieldQueryTest() throwsIOException, ParseException {
// 多个域查询
// 索引库
Directory dir= FSDirectory.open(newFile("/home/lxj/luke/dic"));
// reader对象
IndexReaderreader= IndexReader.open(dir);
// 创建seracher对象
IndexSearchersearcher= newIndexSearcher(reader);
// 使用数值范围查询
// Queryquery =org.apache.lucene.search.NumericRangeQuery.newLongRange("fileSize",100L, 2000L, true, true);
String[]fields= {"fileName","fileContent"};
MultiFieldQueryParsermultiquery= newMultiFieldQueryParser(fields,newIKAnalyzer());
Queryquery= multiquery.parse("apache");
// 获取搜索集
TopDocstopdocs= searcher.search(query,10);
// 获取结果接
ScoreDoc[]docs= topdocs.scoreDocs;
for(ScoreDocdoc:docs){
// doc是一个文件的ID
Document document= reader.document(doc.doc);
System.out.println(document.get("fileName"));
System.out.println(document.get("fileSize"));
}
}