1. Field域
1.1 Field的属性
- 是否分词(Tokenized)
是:对该field存储的内容进行分词,分词的目的,就是为了索引。
比如:商品名称、商品描述、商品价格
否:不需要对field存储的内容进行分词,不分词,不代表不索引,而是将整个内容进行索引。
比如:商品id
- 是否索引(Indexed)
是:将分好的词进行索引,索引的目的,就是为了搜索。
比如:商品名称、商品描述、商品价格、商品id
否:不索引,也就是不对该field域进行搜索。
- 是否存储(Stored)
是:将field域中的内容存储到文档域中。存储的目的,就是为了搜索页面显示取值用的。
比如:商品名称、商品价格、商品id、商品图片地址
否:不将field域中的内容存储到文档域中。不存储,则搜索页面中没法获取该field域的值。
比如:商品描述,由于商品描述在搜索页面中不需要显示,再加上商品描述的内容比较多,所以就不需要进行存储。如果需要商品描述,则根据搜索出的商品ID去数据库中查询,然后显示出商品描述信息即可。
1.2 Field的常用类型
下边列出了开发中常用 的Filed类型,注意Field的属性,根据需求选择:
Field类 |
数据类型 |
Analyzed 是否分词 |
Indexed 是否索引 |
Stored 是否存储 |
说明 |
StringField(FieldName, FieldValue,Store.YES)) |
字符串 |
N |
Y |
Y或N |
这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等) 是否存储在文档中用Store.YES或Store.NO决定 |
LongField(FieldName, FieldValue,Store.YES) |
Long型 |
Y |
Y |
Y或N |
这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格) 是否存储在文档中用Store.YES或Store.NO决定 |
StoredField(FieldName, FieldValue) |
重载方法,支持多种类型 |
N |
N |
Y |
这个Field用来构建不同类型Field 不分析,不索引,但要Field存储在文档中 |
TextField(FieldName, FieldValue, Store.NO) 或 TextField(FieldName, reader)
|
字符串 或 流 |
Y |
Y |
Y或N |
如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略. |
1.3 修改入门程序的代码
for (Book book : list) { document = new Document(); // store:如果是yes,则说明存储到文档域中 // 图书ID // 不分词、索引、存储 StringField Field id = new StringField("id", book.getId().toString(), Store.YES); // 图书名称 // 分词、索引、存储 TextField Field name = new TextField("name", book.getName(), Store.YES); // 图书价格 // 分词、索引、存储 但是是数字类型,所以使用FloatField Field price = new FloatField("price", book.getPrice(), Store.YES); // 图书图片地址 // 不分词、不索引、存储 StoredField Field pic = new StoredField("pic", book.getPic()); // 图书描述 // 分词、索引、不存储 TextField Field description = new TextField("description", book.getDescription(), Store.NO); // 将field域设置到Document对象中 document.add(id); ············· }
2. 索引维护
2.1 需求
图书信息在数据库发生变化,所以索引库相对应的也要发生增删改变化。
2.2 增加索引
语法(具体参照创建索引的程序):IndexWriter.addDocument(document);
······
// a)创建分词器,标准分词器(分析文档,对文档中的Field域进行分词) Analyzer analyzer = new StandardAnalyzer(); // b)创建IndexWriterConfig对象 IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); // c)创建索引库目录,指定索引库的地址 File indexFile = new File("D:\DBIndex\"); Directory directory = FSDirectory.open(indexFile); // d)创建IndexWriter对象 IndexWriter writer = new IndexWriter(directory, cfg); // e)通过IndexWriter对象将Document写入到索引库中 for (Document doc : docList) { writer.addDocument(doc); } // f)关闭writer writer.close();
······
2.2 删除索引
增删改操作,都是需要通过IndexWriter对象来操作。
2.2.1 根据条件删除
Term是索引域中最小的单位。根据条件删除时,建议根据唯一键来进行删除。在solr中就是根据ID来进行删除和修改操作的。
@Test public void deleteIndex() throws Exception { // 创建分词器,标准分词器 Analyzer analyzer = new StandardAnalyzer(); // 创建IndexWriter IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); Directory directory = FSDirectory.open(new File("D:\DBIndex\")); // 创建IndexWriter IndexWriter writer = new IndexWriter(directory, cfg);
// Terms
writer.deleteDocuments(new Term("id", "1")); writer.close(); }
2.3.2 删除全部
@Test public void deleteIndex() throws Exception { // 创建分词器,标准分词器 Analyzer analyzer = new StandardAnalyzer(); // 创建IndexWriter IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); Directory directory = FSDirectory.open(new File("D:\DBIndex\")); // 创建IndexWriter IndexWriter writer = new IndexWriter(directory, cfg); // Terms // writer.deleteDocuments(new Term("id", "1"));
// 删除全部(慎用) writer.deleteAll();
writer.close(); }
2.4 修改索引
@Test public void updateIndex() throws Exception { // 创建分词器,标准分词器 Analyzer analyzer = new StandardAnalyzer(); // 创建IndexWriter IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); Directory directory = FSDirectory.open(new File("D:\DBIndex\")); // 创建IndexWriter IndexWriter writer = new IndexWriter(directory, cfg); // 第一个参数:指定查询条件 // 第二个参数:修改之后的对象 // 修改时如果根据查询条件,可以查询出结果,则将以前的删掉,然后覆盖新的Document对象,如果没有查询出结果,则新增一个Document // 修改流程即:先查询,再删除,在添加 Document doc = new Document(); doc.add(new TextField("name", "lisi", Store.YES)); writer.updateDocument(new Term("name", "zhangsan"), doc); writer.close(); }