咩是索引库的维护 ?
再来一个大白话: 就是针对创好的索引库进行增删改查. 够不够直白.
在前几章说过了创建索引库, 但是在创建 Field 的时候, 使用的都是 TextField.
其实 Field 也是分好多属性的.
Field 域的属性
-
是否需要进行分词
- 前提是这个字段首先要创建索引。然后如果这个字段的值是不可分割的,那么就不需要分词。例如:ID
-
是否需要创建索引
- 将 Field 分析后的词或整个 Field 值进行索引, 只有索引方可搜索到. 比如: 商品名称, 商品简介 分析后进行索引, 订单号, 身份证号不用分析, 但也要索引. 这些将来都要作为查询条件
-
是否需要存储
- 将 Field 值存储在文档中, 存储在文档中的 Field 才可以从 Document 中获取.比如:商品名称, 订单号, 凡是将来要从 Document 中获取的 Field 都要存储.
- 这个简单来说, 只要是一个字段最终要显示到结果中的, 那么就一定要存储. 否则不存储.
1. Field 域的类型
在创建域的时候, 根据实际的数据类型, 来选择域的类型进行创建
Field 类 | 数据类型 | Analyzed 是否分析 | Indexed 是否索引 | Stored 是否存储 | 说明 |
---|---|---|---|---|---|
String Field(FieldName, FieldValue , Store.YES) | 字符串 | N | Y | Y 或N | 这个Field 用来构建一个字符串Field, 但是不会进行分析, 会将整个字符串存储在索引中. 比如(订单号, 姓名等). 是否存储在文档中用 Store.YES / Store.NO决定 |
LongPoint(String name, long point),intPoint ...... | Long 型 | Y | Y | N | 可以使用 LongPoint, IntPoint 等类型存储数值类型的数据, 让数值类型可以进行索引. 但是不能存储数据, 如果想存储数据还需要使用 StoreField |
StoreField(FieldName, FieldValue) | 重载方法, 支持多种类型 | N | N | Y | 这个 Field 用来构建不同类型的 Field, 不拆分,不索引, 但要 Field 存储在文档中, 比如路径等信息. |
TextField(FieldName, FieldValue, Store.NO) 或 TextFiled(FieldName, reader) |
字符串 或流 | Y | Y | Y 或 N | 如果是一个 Reader, Lucene猜测内容比较多, 会采用 Unstored 的策略 |
2. 代码改造.
现在我们知道了域的属性后, 对最开始我们的索引库创建进行代码改造.
Lucene 入门 03 - 全文检索创建的代码实现
- 路径 "path" 我们只需要存储就行了,不需要分析, 所以要换成 StoreField.
- 文件大小"size" 我们不需要进行存储, 但是我们可能又需要计算例如按大小来过滤. 那么使用 LongPoint 来分析并添加索引,但不存储, 使用 StoredField 来存储.
改造后代码如下:
@Test
public void createIndex() throws Exception {
//1.创建一个 Director 对象, 指定索引库保存的位置.把索引保存在磁盘
Directory mDirectory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
//2. 创建一个 IndexWriter 对象
//不再使用默认的分析器, 使用 IK
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new IKAnalyzer());
IndexWriter indexWriter = new IndexWriter(mDirectory, indexWriterConfig);
//读取磁盘上的文件 (我磁盘上放了几个 text)
File dir = new File("/Users/yzhang/Desktop/searchsource");
File[] files = dir.listFiles();
for (File file : files) {
String fileName = file.getName();
String filePath = file.getPath();
String fileContent = FileUtils.readFileToString(file, "utf-8");
long fileSize = FileUtils.sizeOf(file);
//3. 创建域
//args1: 域的名称. args2: 域的内容. args3:是否存储到磁盘
Field fieldName = new TextField("name", fileName, Field.Store.YES);
//变为 StoreField
Field fieldPath = new StoredField("path", filePath);
Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
//使用 LongPoint 进行分析和索引
Field fieldSizeValue = new LongPoint("size", fileSize);
//使用 StoreField 进行存储
Field fieldSizeStore = new StoredField("size", fileSize);
//对每个文件创建文本对象.
Document document = new Document();
///4. 像文档中添加域
document.add(fieldName);
document.add(fieldPath);
document.add(fieldContent);
//添加的时候也要把这两个都添加进去
document.add(fieldSizeValue);
document.add(fieldSizeStore);
//5. 把文档对象写入索引库
indexWriter.addDocument(document);
}
//6. 关闭 indexwriter
indexWriter.close();
}
3. 索引库的增加
添加索引到已存在的索引库
//添加索引
@Test
public void addDocument() throws Exception {
//索引库存放路径
Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
//创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
//创建一个Document对象
Document document = new Document();
//向document对象中添加域。
//不同的document可以有不同的域,同一个document可以有相同的域。
document.add(new TextField("filename", "新添加的文档", Field.Store.YES));
document.add(new TextField("content", "新添加的文档的内容", Field.Store.NO));
//LongPoint创建索引
document.add(new LongPoint("size", 1000l));
//StoreField存储数据
document.add(new StoredField("size", 1000l));
//不需要创建索引的就使用StoreField存储
document.add(new StoredField("path", "d:/temp/1.txt"));
//添加文档到索引库
indexWriter.addDocument(document);
//关闭indexwriter
indexWriter.close();
}
4. 索引库的删除
删除全部
将索引目录的索引信息全部删除,直接彻底删除,无法恢复, 慎用.
@Test
public void deleteAllDocument() throws Exception
//索引库存放路径
Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
//创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
indexWriter.deleteAll();
indexWriter.close();
}
指定查询条件删除
例如: 删除域名为 name 中,关键词为 apache 的文档
@Test
public void deleteDocument() throws Exception
//索引库存放路径
Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
//创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
indexWriter.deleteDocuments(new Term("name","apache"));
indexWriter.close();
}
5. 索引库的修改
- 索引库修改的原理就是先删除再新增一个.
- 修改功能会根据 Term 进行匹配, 所有匹配到的都会被删除. 例如订单 ID,证件号等. 所以我们一般修改的时候, 都会根据一个唯一不重复的字段进行匹配修改. 但是使用 Term ,要求值必须是字符串, 如果不是,则无法使用 Term.
@Test
public void updateIndex() throws Exception
//索引库存放路径
Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
//创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
//创建一个Document对象
Document document = new Document();
document.add(new StringField("name", "zz",Field.Store.YES));
document.add(new TextField("name", "zz1",Field.Store.YES));
document.add(new TextField("name", "zz2",Field.Store.YES));
//更新name 域中 值为 spring 的文档,为新的 Document
indexWriter.updateDocument(new Term("name","spring"), document);
indexWriter.close();
}
下一章重点学习一下查询, Lucene 的查询是很重要的. 所以单独用一个章节来学习.
网友评论