首页 > 代码库 > elasticsearch中一个field多个值如何操作

elasticsearch中一个field多个值如何操作

 在做项目中用到全文检索时遇到这样的需求,有个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 = http://www.mamicode.com/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 = http://www.mamicode.com/this.formatInsertData(values);//格式化处理值
          try {
            if(StringUtils.isNotEmpty(idFieldName) && idFieldName.equals(field)) {
              idValue = http://www.mamicode.com/formatValue;
            }
            doc.field(field, formatValue);
          } catch (IOException e) {
            this.logger.error(e.getMessage());
            return false;
          }          
      }            
    }
    doc.endObject();

    上边标红的部分就是要使用的API方式,同时在进行数据检索时也要注意,这样添加的数据,搜索结果要强转成List类型的,比如我们这里是List<String>。

    

elasticsearch中一个field多个值如何操作