lucene-plus在服务启动后会自动校验配置好的索引信息,索引信息采用json的形式表达,通过实现接口IndexTemplate完成索引信息的配置。为了避免索引信息的混乱,lucene-plus仅实现索引字段的增量维护,如果已有的索引字段发生变更,lucene-plus不会刷新相关的字段信息。关于完成索引信息的配置请参考上一篇博文。
服务启动后,spring会调用LuceneInitialization,触发lucene-plus对已配置的索引信息的加载。
/**
* 初始化索引信息
*
* @throws IOException IOException
*/
private void init() throws IOException {
// 获取所有父类的子类
Map<String, IndexTemplate> beanMap = SpringUtil.getBeansOfType(IndexTemplate.class);
for (Entry<String, IndexTemplate> entry : beanMap.entrySet()) {
IndexTemplate indexTemplate = entry.getValue();
String template = indexTemplate.getTemplate();
IndexTemplateDTO indexTemplateDTO = JSON.parseObject(template, IndexTemplateDTO.class);
List<FieldTemplateDTO> fieldTemplateDTOList = indexTemplateDTO.getFieldDTOList();
// 校验系统占用标识
this.existSystemField(fieldTemplateDTOList);
if (CollUtil.isEmpty(fieldTemplateDTOList)) {
return;
}
List<Document> list = this.indexPlusService.getIndexInfo(indexTemplateDTO.getIndexName());
if (list.size() + fieldTemplateDTOList.size() > LuceneConfig.FIELD_MAX_COUNT) {
throw new AppException(LuceneMsgEnum.FIELD_NUM_MAX_LIMIT);
}
Map<String, Document> docMap = CollUtil.newHashMap();
list.forEach(doc -> docMap.put(doc.get(BasicIndexFieldEnum.FIELD_NAME.getValue()), doc));
// 不存在则初始化基础索引
List<FieldTemplateDTO> initFieldList = fieldTemplateDTOList.stream()
.filter(t -> !docMap.containsKey(t.getFieldName())).collect(
Collectors.toList());
indexTemplateDTO.setFieldDTOList(initFieldList);
this.indexPlusService.initBasicIndex(indexTemplateDTO);
}
}
1、通过fast-json将json转换成IndexTemplateDTO;
2、校验索引的字段信息是否和系统占用字段冲突,目前定义的系统占用的索引名称:["basic_index"],字段名称:["_timestamp"],在定义的索引或字段发生冲突的时候,程序会抛出提示异常;
3、目前lucene-plus限定单个索引最大字段数量是1000,校验定义的索引字段是否超过1000,这个参数定义在LuceneConfig。
4、和存量的索引信息进行比较,把新增的字段初始化到基础索引;
初始化基础索引的代码逻辑参考IndexPlusService#initBasicIndex:
/**
* 保存索引信息
* @param indexTemplateDTO 索引信息
* @throws IOException IOException
*/
public void initBasicIndex(IndexTemplateDTO indexTemplateDTO) throws IOException {
// 创建分词器
StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
// 创建writer
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(standardAnalyzer);
try(IndexWriter indexWriter = new IndexWriter(this.getDirectory(IndexEnum.BASIC_INDEX.getName()), indexWriterConfig)) {
for (FieldTemplateDTO t : indexTemplateDTO.getFieldDTOList()) {
Field indexNameField = new StringField(BasicIndexFieldEnum.INDEX_NAME.getValue(), indexTemplateDTO.getIndexName(), Store.YES);
Field fieldNameField = new StringField(BasicIndexFieldEnum.FIELD_NAME.getValue(), t.getFieldName(), Store.YES);
Field fieldTypeField = new StringField(BasicIndexFieldEnum.FIELD_TYPE.getValue(), t.getFieldType().getType(), Store.YES);
Document doc = new Document();
doc.add(indexNameField);
doc.add(fieldNameField);
doc.add(fieldTypeField);
Store store = null == t.getStore() ? Store.NO : t.getStore();
Field fieldStoreField = new StringField(BasicIndexFieldEnum.FIELD_STORE.getValue(), store.name(), Store.YES);
doc.add(fieldStoreField);
Field fieldPointField = new StringField(BasicIndexFieldEnum.FIELD_POINT.getValue(), null == t.getPoint() ? "false" : t.getPoint().toString(), Store.YES);
doc.add(fieldPointField);
if(null !=t.getAnalyzer()) {
Field analyzerField = new StringField(BasicIndexFieldEnum.FIELD_ANALYZER.getValue(), t.getAnalyzer().name(), Store.YES);
doc.add(analyzerField);
}
indexWriter.addDocument(doc);
indexWriter.commit();
}
}
}
基础索引主要存储业务索引的信息,相关字段参考:BasicIndexFieldEnum
INDEX_NAME("index_name", "索引名称"),
FIELD_NAME("field_name", "字段名称"),
FIELD_TYPE("field_type", "字段类型"),
FIELD_STORE("field_store", "是否存储"),
FIELD_POINT("field_point", "是否支持范围查询"),
FIELD_ANALYZER("field_analyzer", "字段分词器"),
至此完成业务索引的初始化,索引目录如下: