学习目标:
- 明白索引的过程
- 掌握Lucene索引相关的概念
- 熟练使用索引API创建、更新索引
- 会使用索引查看工具Luke
IndexWriter详解
1、架构图
2、Lucene索引创建API 图示
3、Lucene索引创建代码示例
public static void main(String[] args) throws IOException { //创建使用的分词器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); //索引配置对象 IndexWriterConfig config = new IndexWriterConfig(analyzer); //设置索引库的打开模式:新建、追加、新建或追加 config.setOpenMode(OpenMode.CREATE_OR_APPEND); //索引存放目录 //存放到文件系统中 Directory directory = FSDirectory.open((new File("f:/test/indextest")).toPath()); //存放到内存中 //Directory directory = new RAMDirectory(); //创建索引写对象 IndexWriter writer = new IndexWriter(directory, config); //创建document Document doc = new Document(); //往document中添加 商品id字段 doc.add(new StoredField("prodId", "p0001")); //往document中添加 商品名称字段 String name = "ThinkPad X1 Carbon 20KH0009CD/25CD 超极本轻薄笔记本电脑联想"; doc.add(new TextField("name", name, Store.YES)); }
4、IndexWriter涉及类图示
5、IndexWriterConfig 写索引配置:
- 使用的分词器。
- 如何打开索引(是新建,还是追加)。
- 还可配置缓冲区大小、或缓存多少个文档,再刷新到存储中。
- 还可配置合并、删除等的策略。
注意:用这个配置对象创建好IndexWriter对象后,再修改这个配置对象的配置信息不会对IndexWriter对象起作用。
如要在indexWriter使用过程中修改它的配置信息,通过 indexWriter的getConfig()方法获得 LiveIndexWriterConfig 对象,在这个对象中可查看该IndexWriter使用的配置信息,可进行少量的配置修改(看它的setter方法)
6、Directory 指定索引数据存放的位置:
- 内存
- 文件系统
- 数据库
保存到文件系统用法:
Directory directory = FSDirectory.open(Path path); // path指定目录
7、IndexWriter 用来创建、维护一个索引 。它的API使用流程:
public static void main(String[] args) { //创建索引写对象 IndexWriter writer = new IndexWriter(directory, config); //创建document //将文档添加到索引 writer.addDocument(doc); //删除文档 //writer.deleteDocuments(terms); //修改文档 //writer.updateDocument(term, doc); //刷新 writer.flush(); //提交 writer.commit(); }
注意:IndexWriter是线程安全的。
如果你的业务代码中有其他的同步控制,请不要使用IndexWriter作为锁对象,以免死锁。
请查看IndexWriter还提供了哪些:
- add方法
- delete方法
- updatre方法
- 其他方法
8、IndexWriter涉及类图示
Document详解
1、Document 文档
- 要索引的数据记录、文档在lucene中的表示,是索引、搜索的基本单元。一个Document由多个字段Field构成。就像数据库的记录-字段。
- IndexWriter按加入的顺序为Document指定一个递增的id(从0开始),称为文档id。反向索引中存储的是这个id,文档存储中正向索引也是这个id。
- 业务数据的主键id只是文档的一个字段。
2、Document API
3、Field
- 字段:由字段名name、字段值value(fieldsData)、字段类型 type 三部分构成。
- 字段值可以是文本(String、Reader 或 预分析的 TokenStream)、二进制值(byte[])或数值。
4、IndexableField Field API
5、Document—Field 数据举例
- 新闻:新闻id,新闻标题、新闻内容、作者、所属分类、发表时间
- 网页搜索的网页:标题、内容、链接地址
- 商品: id、名称、图片链接、类别、价格、库存、商家、品牌、月销量、详情…
6、IndexableFieldType
- 字段类型:描述该如何索引存储该字段
字段可选择性地保存在索引中,这样在搜索结果中,这些保存的字段值就可获得。
一个Document应该包含一个或多个存储字段来唯一标识一个文档。
注意:未存储的字段,从索引中取得的document中是没有这些字段的。
7、 Document 类关系
8、IndexableFieldType API 说明
9、IndexOptions 索引选项说明:
- NONE 不索引(Not indexed)
- DOCS 反向索引中只存储了包含该词的 文档id,没有词频、位置
- DOCS_AND_FREQS 反向索引中会存储 文档id、词频
- DOCS_AND_FREQS_AND_POSITIONS 反向索引中存储 文档id、词频、位置
- DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS 反向索引中存储 文档id、词频、位置、偏移量
10、Luke 索引查看工具安装
为了查看我们的代码创建的索引情况,请安装工具 luke:
下载地址(当前最新版 7.2.0 可用于lucene7.3.0版):
https://github.com/DmitryKey/luke/releases
11、luke Document 查看说明:
12、IndexableFieldType API 说明:
13、storeTermVectors
对于不需要在搜索反向索引时用到,但在搜索结果处理时需要的位置、偏移量、附加数据(payLoad) 的字段,我们可以单独为该字段存储(文档id词项向量)的正向索引。
- boolean storeTermVectors() 是否存储词项向量
- boolean storeTermVectorPositions() 是否在词项向量中存储位置
- boolean storeTermVectorOffsets() 是否在词项向量中存储偏移量
- boolean storeTermVectorPayloads() 是否在词项向量中存储附加信息
FieldType实现类中有对应的set方法
概念说明:Token trem 词条: 分词得到的词项
14、DocValuesType 选项说明
- NONE 不开启docvalue
- NUMERIC 单值、数值字段,用这个
- BINARY 单值、字节数组字段用
- SORTED 单值、字符字段用, 会预先对值字节进行排序、去重存储
- SORTED_NUMERIC 单值、数值数组字段用,会预先对数值数组进行排序
- SORTED_SET 多值字段用,会预先对值字节进行排序、去重存储
具体使用选择:
- 字符串+单值 会选择SORTED作为docvalue存储
- 字符串+多值 会选择SORTED_SET作为docvalue存储
- 数值或日期或枚举字段+单值 会选择NUMERIC 作为docvalue存储
- 数值或日期或枚举字段+多值 会选择SORTED_SET作为docvalue存储
强调:需要排序、分组、聚合、分类查询(面查询)的字段才创建docValues
15、什么是附加信息Payloads
附加信息非常有用,可用它来存储特殊信息,及减少词项数等
1、空间换时间
对这种需要排序、分组、聚合的字段,为其建立独立的文档->字段值的正向索引、列式存储。这样我们要加载搜中文档的这个字段的数据就快很多,耗内存少。
2、docValuesType
IndexableFieldType 中的 docValuesType方法 就是让你来为需要排序、分组、聚合的字段指定如何为该字段创建文档->字段值的正向索引的。