标签:分布式 lucene 搜索 索引 elasticsearch
在做项目中用到全文检索时遇到这样的需求,有个field的值是多个uuid格式的id组成的字符串,每个id之间用英文逗号分隔,在查询时如果有一个关键字和这个字符串中的一个id一样的话则要取出这个数据。这里要注意,很显然是很难对uuid组成的字符串进行切词的,而且如果uuid很多的情况下使用Lucene的模糊匹配效率也不高。于是我就想了个方案:在创建索引之前就将这个字符串分切成多个id加到同一个field上(还好是Lucene,如果是关系型数据库就不行了),而且不进行分词即可。以下就是涉及到的技术,没有多少技术含量,但是网上关于elasticsearch这方面资料少,反正我是没有查到,经过试验算是搞定了。废话少说:
首先,在Lucene中,如果我们可以在一个Field中加入多个值,比如:
doc.add(new Field("name","北京",Store.YES,Field.Index.NOT_ANALYZED));
doc.add(new Field("name","新德里",Store.YES,Field.Index.NOT_ANALYZED));
这样,当我们针对“name”这个field进行搜索时,如果搜索的关键字是“北京”或者“新德里”则当前这个Document都会被搜索到,这个是Lucene不同于关系型数据库的地方。
那么基于Lucene上的分布式全文索引elasticsearch如何做到呢?经过试验可以使用类似于如下的方式创建索引:
XContentBuilder
doc = XContentFactory.jsonBuilder(); //整个每次循环都需要创建一个,否则会在startObject时报空指针
//添加属性,相当于添加表的字段的值
doc.startObject();
//获取id,如果存在的话
String idValue = null;
for(String field : contextObject.keySet()) {
Object[] values = contextObject.get(field);
//如果是同一个field下多个值,则全部加入到同一个field下
if(null != values && values.length > 1) {
doc.array(field, values);
} else {
String formatValue = this.formatInsertData(values);//格式化处理值
try {
if(StringUtils.isNotEmpty(idFieldName) && idFieldName.equals(field)) {
idValue = formatValue;
}
doc.field(field, formatValue);
} catch (IOException e) {
this.logger.error(e.getMessage());
return false;
}
}
}
doc.endObject();
上边标红的部分就是要使用的API方式,同时在进行数据检索时也要注意,这样添加的数据,搜索结果要强转成List类型的,比如我们这里是List<String>。
标签:分布式 lucene 搜索 索引 elasticsearch
原文地址:http://blog.csdn.net/achilles12345/article/details/41442325