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 = 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>。

时间: 2024-08-30 14:09:49

elasticsearch中一个field多个值如何操作的相关文章

java中一个Map要找到值Value最小的那个元素的方法

import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MinMapDemo {     public static void main(String[] args) {         Map<Integer, Integer> map = new HashMap<Int

关于JAVA中Byte类型的取值范围的推论(*零为正数,-128在计算机中的表示方法...)

先看一段推理<*一切都是在8个比特位的前提下,讨论二进制的符号位,溢出等等,才有意义*> +124:0111 1100 -124:1000 0100 +125:0111 1101 -125:1000 0011 +126:0111 1110 -126:1000 0010 +127:0111 1111 -127:1000 0001 +128:0 1000 0000   -128:1000 0000 从上述过程对比可以看出:+128是在127的基础上加1得到,但是会造成溢出(JAVA中byte的大小

Elasticsearch中使用groovy脚本处理boolean字段的一个问题

Elasticsearch中使用groovy脚本获取文档的bool字段值时,得到的值是字符的 'T' 或者 'F' ,而不是bool值 true 和 false . 比如文档中有一个字段是 { "bool_value":true } 然后用这个字段判断时候得写成 if (doc['bool_value'].value == 'T') { //blahblah } else { //blahblah }

在map中一个key中存多个值

一说到map都想到key-value键值队存在.key可以为最多一个null的key. 今天开发中一个业务需求,在map中一个key中存多个对象. 我首先想到Map<String,List>造型来解决.尤其是那种一对多的可以这么设计. Map<String,List> map = new HashMap<String,List>();//模型就是这么个. for(int i=0;i<listObj.size();i++){ key = listObj.getId(

利用matlab提取并分割RGB图像中的某一个已知像素值的图像

已知一副RGB图像中的的像素值,利用matlab将其分割出来并以二进制图像形式显示: %extract.m clear all; I=imread('new_original.png'); figure,imshow(I),title('Original Image'); bw=im2bw(I,0.3); %figure,imshow(bw),title('Gray Image'); rgb=[252,2,4]; img=extract_rgb(I,rgb); figure,imshow(im2

SQL将一个表中的某一列值全部插入到另一个表中

1.  SQL将一个表中的某一列值全部插入到另一个表中 插入的话: insert into a(col) select col from b; 更新的话: update a set col=select col from b where a.id=b.id; 判断表是否存在数据库中,存在就删除 if exists (select * from Sysobjects where name='temp') begin drop table temp end

4、CRM2011编程实战——将窗体中指定控件的值做处理后更新到另一个字段中

需求:将接报时间加上到期提醒时间后得到的值,更新到字段"到期截止时间" Js调用: //设置到期截止时间 function setDeadLine(){ var recordId = Xrm.Page.data.entity.getId(); var entityName = Xrm.Page.data.entity.getEntityName(); var reportedTime = Xrm.Page.getControl("hxcs_fdatetimeofrequest

SQL 将一条记录中多个字段的值拼接为一个字段 &amp;&amp; 将多行数据合并成一行,并且拼接CONVERT() 、for xml path的使用

接着上篇文章的订单表(商品编号,价格设置时间id(类似于创建时间,创建时间约早,则act_id越小) ,价格的时间段,商品价格) 一.将一条记录中多个字段的值拼接为一个字段 现要求将两个时间段合并为一个字段,应该如何做呢? 先来看下理想的结果: 查询出的时间段合并到一起了: 代码如下,将查询的字段用+'你想要的符号' + 拼接即可 select item,act_id,loc_id,convert(varchar(100),start_date,20)+ '-' +convert(varchar

返回一个整数数组中最大子数组的值(程序能处理1000个元素)

课堂练习: 题目:要求返回一个整数数组中最大子数组的值 要求:程序必须能处理1000个元素 每个元素是int32类型的 设计思路: 将数组的大小定义为1000,每个元素定义为int32类型,取数值时对数成2的32次方,这样数值可以越界. 程序: #include <iostream>  #include<stdlib.h>  #include<time.h>  using namespace std;    int main()  {     int i;     in