随着ElasticSearch应用的不断增多,我发现它作为全文数据库功能确实非常强大。
我本人使用的是java客户端TransportClient操作es,如果采用原生的API,或多或少存在一些不便之处。比如创建索引,添加索引文件,修改索引文件,删除索引文件,如果不加以封装,在实际应用时需要花大量时间学习api的使用,同时造成大量代码重复。
因为项目需要,我针对索引创建,修改和删除进行了一定的代码封装。 特别是在索引的创建,我在这里封装了创建静态mapping索引的方法,并且提供了一个只需要传入任意javabean对象,就为其创建符合使用要求的静态mapping索引的方法。
以下代码在使用时,可直接在springboot创建的项目中写一个配置类,需要传入一个client对象,或者同时传入client和Jedis对象(如果需要的话)。
话不多说,直接上代码:
package cn.yumi.common.utils;
import jdk.nashorn.internal.ir.RuntimeNode;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import redis.clients.jedis.JedisCluster;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @ClassName IndexUtil
* @Description TODO
* @Author GrainRain
* @Date 2020/1/13 21:09
* @Version v1.0
*/
public class IndexClient {
private TransportClient client;
private JedisCluster jedisCluster;
public IndexClient(TransportClient client){
this.client = client;
}
public IndexClient(TransportClient client,JedisCluster jedisCluster){
this.client = client;
this.jedisCluster = jedisCluster;
}
//根据indexName创建索引
public void createIndexByJson(String indexName) throws IOException {
IndicesAdminClient indices = client.admin().indices();
boolean exists = indices.prepareExists(indexName).get().isExists();
if(exists)
return;
//索引不存在,指定mapping,此处采用json指定,需注意json结构
CreateIndexRequestBuilder request = indices.prepareCreate(indexName); //指定索引名称
//提交并创建索引
request.get();
}
//根据静态mapping创建索引
public void createIndexByJson(String indexName, String type, Map<String, Map<String,String>> fieldsMap) throws IOException {
//获取索引管理器
IndicesAdminClient indices = client.admin().indices();
boolean exists = indices.prepareExists(indexName).get().isExists();
//指定索引名称
CreateIndexRequestBuilder request = indices.prepareCreate(indexName);
if(exists) { //索引已存在,执行新增操作
return;
}
//获取构建静态mapping的builder
XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("properties");
//将传入的静态mapping参数依次封装到mapping中
Set<String> fields = fieldsMap.keySet();
for(String field: fields){
Map<String, String> fieldType = fieldsMap.get(field);
mapping.startObject(field);
for(Map.Entry<String,String> entry :fieldType.entrySet()){
mapping.field(entry.getKey(),entry.getValue());
}
mapping.endObject();
}
//关闭json构造
mapping.endObject().endObject();
//添加mapping并创建索引
request.addMapping(type, mapping);
request.execute().actionGet();
}
//根据javaBean创建静态索引
/*
按照javabean的属性值创建具有静态mapping的索引
如果值为null,采用keyword类型
如果值为中文,采用text类型并默认ik分词器
如果值为数值,采用long类型
*/
public void createIndex(String indexName, String type, Object o){
Map<String,Map<String,String>> mapping = new HashMap<>();
try {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field:fields) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(o);
if(value==null){
Map<String,String> map = new HashMap<>();
map.put("type","keyword");
mapping.put(name,map);
} else if(value.getClass()==Integer.class || value.getClass()==Long.class || value.getClass()==int.class || value.getClass()==long.class){
Map<String,String> map = new HashMap<>();
map.put("type","long");
mapping.put(name,map);
}else if(value.getClass()==String.class){
String key = (String)value;
Map<String,String> map = new HashMap<>();
if(key.matches("[a-zA-z0-9\\\\/\\-\\.\\?=!]+")){
map.put("type","keyword");
mapping.put(name,map);
}else{
map.put("type","text");
map.put("analyzer","ik_max_word");
mapping.put(name,map);
}
}
}
System.out.println(mapping);
this.createIndexByJson(indexName,type,mapping);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException();
}
}
//添加文档到索引中
public void addDoc(String indexName,String type,List<String> docs) {
if(docs != null){
for (String doc:docs){
IndexRequestBuilder request = client.prepareIndex(indexName, type,IDCreateUtil.getId()).setSource(doc);
request.get();
}
}
}
public void addDoc(String indexName,String type,String doc) {
IndexRequestBuilder request = client.prepareIndex(indexName, type,IDCreateUtil.getId()).setSource(doc);
request.get();
}
//支持指定id后添加到数据库
public void addDoc(String indexName,String type,Map<String,String> idAndDocs){
if(idAndDocs != null){
for(Map.Entry<String,String> entry : idAndDocs.entrySet()){
String id = entry.getKey();
String doc = entry.getValue();
IndexRequestBuilder request = client.prepareIndex(indexName,type,id).setSource(doc);
request.get();
}
}
}
public void addDoc(String indexName,String type,String id,String doc){
IndexRequestBuilder request = client.prepareIndex(indexName, type,id).setSource(doc);
request.get();
}
//扫描redis数据并加入全文数据库
public void scanDoc(String indexName,String type) {
String typeName = "es_index:" + type;
List<String> list = new ArrayList<String>();
while (jedisCluster.llen(typeName) != 0) {
String json = jedisCluster.rpop(typeName);
list.add(json);
//达到1000条数据,先处理这批数据,然后再继续扫描
if(list.size()>1000)
this.addDoc(indexName,type,list);
}
//数据量小于1000,直接处理
this.addDoc(indexName,type,list);
}
//将接收的数据加入redis以等待被加入es,或者直接加入
public void addDocToRedis(String indexName,String type,String oJson,String isAddNow) {
if ("true".equals(isAddNow) && indexName != null && !"".equals(indexName)) {
this.addDoc(indexName,type,oJson);
} else {
String key = "es_index:" + type;
jedisCluster.lpush(key, oJson);
}
}
//此处map的key-value为需要更新的文档属性及对应更新后的值
public void updateDoc(String indexName,String type,String id,Map<String,Object> sources){
UpdateRequest request = new UpdateRequest(indexName,type,id);
request.doc(sources);
client.update(request);
}
public void updateDoc(String indexName,String type,String id,String sources){
UpdateRequest request = new UpdateRequest(indexName,type,id);
request.doc(sources);
client.update(request);
}
public void deleteDoc(String indexName,String type,String id){
DeleteRequest request = new DeleteRequest(indexName,type,id);
client.delete(request);
}
public List<String> queryIndexId(QueryBuilder query, String ...indices){
SearchRequestBuilder request = client.prepareSearch(indices);
request.setQuery(query);
SearchHits hits = request.get().getHits();
List<String> idList = new ArrayList<String>();
for(SearchHit hit:hits){
idList.add(hit.getId());
}
return idList;
}
}