Field域
Field是文档中的域,包括Field名和Field值两部分,一个文档可以包括多个Field,Document只是Field的一个承载体,Field值即为要索引的内容,也是要搜索的内容。
Field属性
是否分词 (tokenized)
- 是:作分词处理,即将Field值进行分词,分词的目的是为了索引。
比如:商品名称、商品描述等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分词后将语汇单元建立索引
- 否:不作分词处理
比如:商品id、订单号、身份证号等
是否索引 (indexed)
- 是:进行索引。将Field分词后的词或整个Field值进行索引,存储到索引域,索引的目的是为了搜索。
比如:商品名称、商品描述分析后进行索引,订单号、身份证号不用分词但也要索引,这些将来都要作为查询条件。
- 否:不索引。如果不需要索引就不需要分词。
比如:图片路径、文件路径等,不用作为查询条件的不用索引。
是否存储 (stored)
- 是:将Field值存储在文档域中,存储在文档域中的Field才可以从Document中获取。
比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。
- 否:不存储Field值
比如:商品描述,内容较大不用存储。如果要向用户展示商品描述可以从系统的关系数据库中获取
Field类型
下边列出了开发中常用 的Filed类型,注意Field的属性,根据需求选择:
Field类 | 数据类型 | Analyzed是否分词 | Indexed是否索引 | Stored是否存储 | 说明 |
---|---|---|---|---|---|
StringField(FieldName,FieldValue,Store.YES)) | 字符串 | N | Y | Y或N | 这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等)是否存储在文档中用Store.YES或Store.NO决定 |
FloatPoint(FieldName, FieldValue) | Float型 | Y | Y | N | 这个Field用来构建一个Float数字型Field,进行分词和索引,不存储, 比如(价格) 存储在文档中 |
DoublePoint(FieldName,FieldValue) | Double型 | Y | Y | N | 这个Field用来构建一个Double数字型Field,进行分词和索引,不存储 |
LongPoint(FieldName, FieldValue) | Long型 | Y | Y | N | 这个Field用来构建一个Long数字型Field,进行分词和索引,不存储 |
IntPoint(FieldName, FieldValue) | Integer型 | Y | Y | N | 这个Field用来构建一个Integer数字型Field,进行分词和索引,不存储 |
StoredField(FieldName, FieldValue) | 重载方法,支持多种类型 | N | N | Y | 这个Field用来构建不同类型Field不分析,不索引,但要Field存储在文档中 |
TextField(FieldName, FieldValue, Store.NO) 或 TextField(FieldName,reader) | 字符串或流 | Y | Y | Y或N | 如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略. |
NumericDocValuesField(FieldName,FieldValue) | 数值 | - | - | - | 配合其他域排序使用 |
对于数值类型的数据,分词可以实现范围查询。
索引维护
更新
管理人员通过电商系统更改图书信息,这时更新的是关系数据库,如果使用lucene搜索图书信息,需要在数据库表book信息变化时及时更新lucene索引库。
示例:
@Test
public void updateIndexTest() throws Exception{
// 创建更改目标对象
Document document = new Document();
document.add(new StringField("id","100000003145", Field.Store.YES));
document.add(new TextField("name", "xxx",Field.Store.YES));
document.add(new IntPoint("price", 123));
document.add(new StoredField("price", 123));
document.add(new StoredField("image", "xxx.jpg"));
document.add(new StringField("categoryName", "手机",Field.Store.YES));
document.add(new StringField("brandName", "华为",Field.Store.YES));
// 创建分词器
Analyzer analyzer = new StandardAnalyzer();
// 创建Directory目录对象,表示索引库的位置
Directory dir = FSDirectory.open(Paths.get("D:\\dir"));
// 创建IndexWriterConfig对象,指定切分词使用的分词器
IndexWriterConfig config = new IndexWriterConfig(analyzer);
// 创建IndexWriter输出流对象,指定输出的位置和使用的config初始化对象
IndexWriter indexWriter = new IndexWriter(dir,config);
// 修改,第一个参数:修改条件,第二个参数:修改成的内容
indexWriter.updateDocument(new Term("id","100000003145"),document);
// 释放资源
indexWriter.close();
}
Lucene的修改实际是将对应的文档删除然后新建文档。
注意,不能添加一个域类型和其他文档的域不一样的文档,否则打开索引库会报错:
java.lang.IllegalArgumentException: cannot change field "brandName" from index options=DOCS to inconsistent index options=DOCS_AND_FREQS_AND_POSITIONS
at org.apache.lucene.index.FieldInfo.update(FieldInfo.java:154) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.index.FieldInfosBuilder.addOrUpdateInternal(FieldInfos.java:534) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.index.FieldInfosBuilder.add(FieldInfos.java:559) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.index.FieldInfosBuilder.add(FieldInfos.java:554) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.index.FieldInfosBuilder.add(FieldInfos.java:480) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.index.FieldInfos.getMergedFieldInfos(FieldInfos.java:154) ~[luke-swing-with-deps.jar:?]
at org.apache.lucene.luke.models.util.IndexUtils.getFieldInfos(IndexUtils.java:379) ~[luke-swing-with-deps.jar:?]
......
删除
@Test
public void deleteIndexTest() throws Exception{
// 创建分词器,StandardAnalyzer对英文分词效果好,对中文是单字分词
Analyzer analyzer = new StandardAnalyzer();
// 创建Directory目录对象,表示索引库的位置
Directory dir = FSDirectory.open(Paths.get("D:\\dir"));
// 创建IndexWriterConfig对象,指定切分词使用的分词器
IndexWriterConfig config = new IndexWriterConfig(analyzer);
// 创建IndexWriter输出流对象,指定输出的位置和使用的config初始化对象
IndexWriter indexWriter = new IndexWriter(dir,config);
// 删除
indexWriter.deleteDocuments(new Term("id","100000003145"));
// 释放资源
indexWriter.close();
}
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/lucene%e4%b8%ad%e7%9a%84%e5%9f%9f%e7%b1%bb%e5%9e%8b%e5%8f%8a%e6%96%87%e6%a1%a3%e7%9a%84%e6%9b%b4%e6%96%b0-%e5%88%a0%e9%99%a4/