lucene的增删改查代码及配置
增删改查
// 创建索引
@Test
public void createIndex() throws Exception {
/*
第一步:创建一个indexwriter对象。
1)指定索引库的存放位置Directory对象
2)指定一个分析器,对文档内容进行分析。*/
// 指定索引库的存放位置Directory对象
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
// 索引库还可以存放到内存中
// Directory directory = new RAMDirectory();
// 指定一个分析器,对文档内容进行分析
Analyzer analyzer = new IKAnalyzer();
// 第一个参数: Lucene的版本信息,可以选择对应的lucene版本也可以使用LATEST
// 第二个参数:分析器对象
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
// 创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
// 要创建索引的文件夹地址
File f = new File("E:\\searchsource");
File[] files = f.listFiles();
for (File file : files) {
//第二步:创建document对象。
Document document = new Document();
// 文件名称
String fileName = file.getName();
//第三步:创建field对象,将field添加到document对象中。
Field fileNameField = new TextField("fileName", fileName, Field.Store.YES);
// 文件大小
long fileSize = FileUtils.sizeOf(file);
Field fileSizeField = new LongField("fileSize", fileSize, Field.Store.YES);
// 文件路径
String filePath = file.getPath();
Field filePathField = new StoredField("filePath", filePath);
// 文件内容
String fileContent = FileUtils.readFileToString(file);
Field fileContentField = new TextField("fileContent", fileContent, Field.Store.YES);
document.add(fileNameField);
document.add(fileSizeField);
document.add(filePathField);
document.add(fileContentField);
//第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
indexWriter.addDocument(document);
}
//第五步:关闭IndexWriter对象。
indexWriter.close();
System.out.println("lucene创建索引");
}
//搜索索引
@Test
public void searchIndex() throws Exception {
//第一步:创建一个Directory对象,也就是索引库存放的位置。(磁盘的位置)
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
//第二步:创建一个indexReader对象,需要指定Directory对象。
IndexReader indexReader = DirectoryReader.open(directory);
//第三步:创建一个indexsearcher对象,需要指定IndexReader对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。TermQuery(精准查询)
Query query = new TermQuery(new Term("fileContent", "北京"));
//第五步:执行查询。第一个参数是查询对象,第二个参数是查询结果返回的最大值
TopDocs topDocs = indexSearcher.search(query, 1000);
//第六步:返回查询结果。遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//第七步:关闭IndexReader对象
indexReader.close();
}
// 1.删除所有
// 2.删除指定索引
@Test
public void deleteIndex() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
Analyzer analyzer = new IKAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
IndexWriter indexWriter = new IndexWriter(directory, config);
//1.删除所有
//indexWriter.deleteAll();
//indexWriter.close();
// 2.删除指定索引
Query query = new TermQuery(new Term("fileContent", "北京"));
indexWriter.deleteDocuments(query);
indexWriter.close();
}
//修改
//更新操作: 按照Term进行指定域搜索关键字,如果查到记录就删除,
//然后将更新后的内容重新生成Document对象
//如果没有查到记录,则直接将更新后的内容添加一个Document对象
@Test
public void updateIndex() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
Analyzer analyzer = new IKAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
IndexWriter indexWriter = new IndexWriter(directory, config);
Document doc = new Document();
doc.add(new TextField("fileName", "文本", Field.Store.YES));
doc.add(new LongField("fileSize", 100L, Field.Store.YES));
doc.add(new StringField("fileContent", "文本", Field.Store.YES));
indexWriter.updateDocument(new Term("fileContent", "http"), doc, new IKAnalyzer());
indexWriter.close();
}
//query的子类查询
//(1)查询所有,使用MatchAllDocsQuery查询索引目录中的所有文档
@Test
public void searchAll() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//查询所有
Query query = new MatchAllDocsQuery();
TopDocs topDocs = indexSearcher.search(query, 20);
//执行查询结果,遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//关闭IndexReader对象
indexReader.close();
}
//(2)精确查询,TermQuery不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。上述搜索索引时使用的就是这种查询
//(3)根据数值查询,可以根据数值范围查询。
@Test
public void searchByNum() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//NumericRangeQuery可以根据数值范围查询 参数:1.域名 2.最小值 3.最大值 4.是否包含最小值 5.是否包含最大值
Query query = NumericRangeQuery.newLongRange("fileSize", 1l, 100l, true, true);
TopDocs topDocs = indexSearcher.search(query, 20);
//执行查询结果,遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//关闭IndexReader对象
indexReader.close();
}
//(4)组合条件查询,可以组合查询条件
@Test
public void BooleanQuery() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//创建一个布尔查询对象
BooleanQuery query = new BooleanQuery();
//创建第一个查询条件
Query query1 = new TermQuery(new Term("fileName", "北京"));
Query query2 = new TermQuery(new Term("fileContent", "北京"));
//组合查询条件
query.add(query1, BooleanClause.Occur.MUST);
query.add(query2, BooleanClause.Occur.MUST);
TopDocs topDocs = indexSearcher.search(query, 20);
//执行查询结果,遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//关闭IndexReader对象
indexReader.close();
}
使用queryparser查询
/*
* 使用queryparser查询
* 通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。
* Query对象执行的查询语法可通过System.out.println(query);查询。
* 需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。
* 需要加入queryParser依赖的jar包。
* */
@Test
public void QueryParser() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// 创建queryparser对象(第一个参数默认搜索的域,第二个参数就是在查询的时候采用的分析器对象,搜索的值可能是一段话)
QueryParser queryParser = new QueryParser("fileContent", new IKAnalyzer());
// *:* =(域:值) 当前的值使用的事默认的域,这里用的是语法
Query query = queryParser.parse("北京的");
// 不使用默认的域,也可以自己指定域
//Query query = queryParser.parse("fileContent:数据");
TopDocs topDocs = indexSearcher.search(query, 20);
//执行查询结果,遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//关闭IndexReader对象
indexReader.close();
}
指定多个默认搜索域查询
/*
* 指定多个默认搜索域:MultiFieldQueryParser
* */
@Test
public void multiFiledQueryParser() throws Exception {
FSDirectory directory = FSDirectory.open(new File("E:\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//可以指定默认搜索的域是多个
String[] fields = {"fileName", "fileContent"};
// 创建queryparser对象(第一个参数默认搜索的域,第二个参数就是在查询的时候采用的分析器对象,搜索的值可能是一段话)
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
// *:* =(域:值) 当前的值使用的事默认的域,这里用的是语法
Query query = queryParser.parse("北京 好地方,津京翼都很好");
TopDocs topDocs = indexSearcher.search(query, 20);
//执行查询结果,遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("关键字:[" + "" + "],出现了:" + scoreDocs.length + " 次。");
for (ScoreDoc scoreDoc : scoreDocs) {
//scoreDoc.doc属性就是document对象的id
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println("名称:" + fileName);
// 文件内容
System.out.println("出现的文件内容:");
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println("大小:" + fileSize);
System.out.println("--------------------------------------------------------");
}
//关闭IndexReader对象
indexReader.close();
}
查看标准分析器的分词效果
//查看标准分析器的分词效果
@Test
public void testTokenStream() throws Exception {
//创建一个标准分析器对象
Analyzer analyzer = new IKAnalyzer();
//获得tokenStream对象,第一个参数:域名,可以随便给一个;第二个参数:要分析的文本内容
TokenStream tokenStream = analyzer.tokenStream("test", "我爱北京天安门.津京翼是三个地方");
//添加一个引用,可以获得每个关键词
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
//添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
//将指针调整到列表的头部
tokenStream.reset();
//遍历关键词列表,通过incrementToken方法判断列表是否结束
while (tokenStream.incrementToken()) {
//关键词的起始位置
System.out.println("start->" + offsetAttribute.startOffset());
//取关键词
System.out.println(charTermAttribute);
//结束位置
System.out.println("end->" + offsetAttribute.endOffset());
}
tokenStream.close();
}
需要的jar!
配置
ext.dic文件 内容是自己定义扩展的词汇来分词;
stopword.dic文件 内容是自己禁止词汇来分词:
在 IKAnalyzer.cfg.xml 中配置以上两个文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">ext.dic;</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">stopword.dic;</entry>
</properties>