个人博客 地址:http://www.wenhaofan.com/article/20180921233809
问题描述
在使用deleteDocuments,updateDocument方法根据id字段删除更新索引时不抛异常但是删除更新失败
writer.deleteDocuments(new Term("id", "1"));
解决问题
在创建索引时使用到了lucene提供的StoreField TextField,而id字段的属性的类型为StoreField,当出现该问题时首先切换思路尝试根据content删除索引。writer.deleteDocuments(new Term("content", "html"));果不其然,使用类型为TextField时便能正确的执行删除修改操作,但是由于TextField属性有一个特性 ,使用该类型的字段会被分词,这样便会出现一个问题。
假如我们使用TextFiled来存储了一个id为123的字段,一个id值为12的字段。
由于TextField类型的值会被分词,所以id值为123的文档可能会创建两个索引:12和123 ,id值为12的文档可能会创建一个索引:12 (实际情况或许不会如此,此处仅作演示)。
此时如果我们想要删除id值为12的文档,便很有可能同时删掉id值为123的文档,因为他们有一个共同的索引值12。
所以使用TextField来存储id值不是一个理想的解决方法,继续寻找其他的解决 方法。
现在问题的原因基本上能够锁定在StoreFiled和TextField的差异上,所以进一步分析问题原因,
最后通过阅读源码发现TextField设置了FieldType中的IndexOptions属性值为IndexOptions.DOCS_AND_FREQS_AND_POSITIONS,而StoredField中的FieldType并没有设置该属性
于是修改建立索引时id所使用的Filed,代码修改如下
将
Field idField=new Field("id", String.valueOf(article.getId()), type)修改为
FieldType type = new FieldType(); type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); type.setTokenized(false); type.setStored(true); Field idField=new Field("id", String.valueOf(article.getId()), type);
此处新建了一个不进行分词,IndexOptions属性值为IndexOptions.DOCS_AND_FREQS_AND_POSITIONS,且存储在查询结果中的FieldType,经测试 完美解决问题