JAVA 操作ES基础使用实现

一:运行环境

    JDK:1.8

    ES:5.6.4

二:JAVA依赖环境

    elasticsearch.jar  5.6.4版本;

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath />
	</parent>


	<groupId>com.huize.pluto.els</groupId>
	<artifactId>demo</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<elasticsearch.version>5.6.4</elasticsearch.version>
		<java.version>1.8</java.version>
	</properties>

	<repositories>
		<repository>
			<id>spring-libs-milestone</id>
			<url>https://repo.spring.io/libs-milestone</url>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-plugins-release</id>
			<url>https://repo.spring.io/plugins-release</url>
		</pluginRepository>
	</pluginRepositories>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        
        <!-- 强制声明ES版本 -->
		<dependency>
			<groupId>org.elasticsearch</groupId>
			<artifactId>elasticsearch</artifactId>
			<version>${elasticsearch.version}</version>
		</dependency>
		
        <!-- 因为要采用java编码直接操作ES所以需要引入 -->
		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>transport</artifactId>
			<version>${elasticsearch.version}</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		
	</dependencies>


	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<compilerVersion>1.8</compilerVersion>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

 

三、ES API

3.1:配置ES

声明ES的 Client  bean 


/***
 ** 配置ES,支持集群
 */
@Configuration
public class ElasticConfigration {

    @Value("${elasticsearch.host}")
    private String esHost;

    @Value("${elasticsearch.port}")
    private int esPort;

    @Value("${elasticsearch.clusterName}")
    private String esClusterName;
    
    private TransportClient client;
    
    @PostConstruct
    public void initialize() throws Exception {
	   Settings esSettings = Settings.builder()
                  .put("cluster.name", esClusterName)
                  .put("client.transport.sniff", true).build();
	   client = new PreBuiltTransportClient(esSettings);

	   String[] esHosts = esHost.trim().split(",");
	   for (String host : esHosts) {
	       client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), 
           esPort));
	   }
    }
    
    @Bean
    public Client client() {
	   return client;
    }
    
    
    @PreDestroy
    public void destroy() {
	  if (client != null) {
	       client.close();
	   }
    }

}

3.2:编写实体类

声明各个字段类型及相应属性:

/**
 * 声明 USER实体,注意有一个1对多关系的roles
 **/
public class User {
    
    
    private String id;
    
    
    private String userName;
    
    
    private Integer age;
    
    
    private Date birthday;
    
    
    private String description;
    
    /**
     * 1对多在spring-data-elasticsearch 统一为nested类型
     **/
    private List<Role> roles;
    
    
    public User() {}
    
    public User(String userName,Integer age,Date birthday,String description) {
	   this.userName = userName;
	   this.age = age;
	   this.birthday = birthday;
	   this.description = description;
    }
    
    public String getId() {
        return id;
    }

    
    public void setId(String id) {
        this.id = id;
    }

    
    public String getUserName() {
        return userName;
    }

    
    public void setUserName(String userName) {
        this.userName = userName;
    }

    
    
    public Date getBirthday() {
        return birthday;
    }


    
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }


    public Integer getAge() {
        return age;
    }

    
    public void setAge(Integer age) {
        this.age = age;
    }

    
    public String getDescription() {
        return description;
    }

    
    public void setDescription(String description) {
        this.description = description;
    }

    
    public List<Role> getRoles() {
        return roles;
    }

    
    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
    
    
}


public class Role {
    
    
    private String id;
    
    
    private String name;
    
    
    private Date createTime;
    
    
    private String description;
    
    public Role() {}
    
    public Role(String name,String description,Date createTime) {
	this.name = name;
	this.description = description;
	this.createTime = createTime;
    }
    
    public String getId() {
        return id;
    }

    
    public void setId(String id) {
        this.id = id;
    }

    
    public String getName() {
        return name;
    }

    
    public void setName(String name) {
        this.name = name;
    }

    
    public Date getCreateTime() {
        return createTime;
    }

    
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    
    public String getDescription() {
        return description;
    }

    
    public void setDescription(String description) {
        this.description = description;
    }
    
}

3.2:编写dao

依靠 ES api提供的 Client对象来完成增删改查功能

@Component
public class ElasticOperationService {

    private final Logger logger = LoggerFactory.getLogger(ElasticOperationService.class);

    @Autowired
    private Client client;
    
    private BulkProcessor bulkProcessor;
    
    @PostConstruct
    public void initBulkProcessor() {

	   bulkProcessor = BulkProcessor.builder(client, new BulkProcessor.Listener() {
     
     	    @Override
     	    public void beforeBulk(long executionId, BulkRequest request) {
     		logger.info("序号:{} 开始执行{} 条记录保存",executionId,request.numberOfActions());
     	    }
     
     	    @Override
     	    public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
     		logger.error(String.format("序号:%s 执行失败; 总记录数:%s",executionId,request.numberOfActions()),failure);
     	    }
     
     	    @Override
     	    public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
     		logger.info("序号:{} 执行{}条记录保存成功,耗时:{}毫秒,",executionId,request.numberOfActions(),response.getTookInMillis());
     	    }
     	}).setBulkActions(1000)
     		.setBulkSize(new ByteSizeValue(10, ByteSizeUnit.MB))
     		.setConcurrentRequests(4)
     		.setFlushInterval(TimeValue.timeValueSeconds(5))
     		.setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(500),3))  //失败后等待多久及重试次数
     		.build();
    }
    
    
    @PreDestroy
    public void closeBulk() {
    	if(bulkProcessor != null) {
    	    try {
    		bulkProcessor.close();
    	    }catch (Exception e) {
    		logger.error("close bulkProcessor exception",e);
    	    }
    	}
    }
    
 
    /**
     * 批量添加,性能最好
     * 
     */
    public void addDocumentToBulkProcessor(String indices, String type, Object object) {
	    bulkProcessor.add(client.prepareIndex(indices, type).setSource(JsonUtils.beanToJson(object)).request());
    }
    
    
    public void addDocument(String indices, String type, Object object) {
	    IndexResponse resp = client.prepareIndex(indices, type).setSource(JsonUtils.beanToJson(object)).get();
	    logger.info("添加结果:{}",resp.toString());
    }

    /**
     * 按id删除
     * 
     */
    public void deleteDocumentById(String index, String type, String id) {
	   // new DeleteByQueryRequest(search);
	   DeleteResponse resp = client.prepareDelete(index, type, id).get();
	    logger.info("删除结果:{}",resp.toString());
    }

    /**
     * 按条件删除
     * 
     */
    public void deleteDocumentByQuery(String index, String type, UserSearchParam param) {
    	
    	//DeleteByQueryRequestBuilder builder = new DeleteByQueryRequestBuilder(client,DeleteByQueryAction.INSTANCE);
    	DeleteByQueryRequestBuilder builder = DeleteByQueryAction.INSTANCE.newRequestBuilder(client);
    	
    	//builder.filter(convertParam(param));
    	builder.source().setIndices(index).setTypes(type).setQuery(convertParam(param));
    	BulkByScrollResponse resp = builder.get();
    	logger.info("删除结果:{}",resp.toString());
    }

    /**
     * 按ID更新
     * 
     */
    public void updateDocument(String indices, String type,String id,Object object) {
    	UpdateResponse resp = client.prepareUpdate(indices, type, id).setDoc(JsonUtils.beanToJson(object)).get();
    	logger.info("更新结果:{}",resp.toString());
    }
    

    /**
     * 按条件更新
     * 
     */
    public void updateDocumentByQuery(String indices, String type, Object object,UserSearchParam param) {
    	//UpdateByQueryRequestBuilder builder = new UpdateByQueryRequestBuilder(client,UpdateByQueryAction.INSTANCE);
    	UpdateByQueryRequestBuilder builder = UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
    	builder.source().setIndices(indices).setTypes(type).setQuery(convertParam(param));
    }
    
    
    public <T> List<T> queryDocumentByParam(String indices, String type,UserSearchParam param,Class<T> clazz) {
    	SearchRequestBuilder builder = buildRequest(indices,type);
    	builder.addSort("birthday",SortOrder.ASC);
    	builder.setQuery(convertParam(param));
    	builder.setFrom(0).setSize(10);
    	SearchResponse resp = builder.get();
    	return convertResponse(resp,clazz);
    }

    private BoolQueryBuilder convertParam(UserSearchParam param) {

    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	if (StringUtils.hasText(param.getUserName())) {
    	    boolQueryBuilder.must(QueryBuilders.termQuery("userName", param.getUserName()));
    	}
    	if (param.getAge() != null) {
    	    boolQueryBuilder.must(QueryBuilders.rangeQuery("age").gt(param.getAge()));
    	}
    	if (StringUtils.hasText(param.getDescription())) {
    	    boolQueryBuilder.must(QueryBuilders.matchQuery("description", param.getDescription()));
    	}
    	if(StringUtils.hasText(param.getRoleName())) {
    	    boolQueryBuilder.must(QueryBuilders.nestedQuery("roles", QueryBuilders.termQuery("roles.name", param.getRoleName()), ScoreMode.None));
    	}
    	
    	return boolQueryBuilder;
    }
    

    /**
     * 通用的装换返回结果
     * 
     */
    public <T> List<T> convertResponse(SearchResponse response,Class<T> clazz) {
    	List<T> list = Lists.newArrayList();
    	if(response != null && response.getHits() != null) {
    	    String result = org.apache.commons.lang3.StringUtils.EMPTY;
    	    T e = null;
    	    Field idField = ReflectionUtils.findField(clazz, "id");
    	    if (idField != null) {
    		ReflectionUtils.makeAccessible(idField);
    	    }
    	    for(SearchHit hit : response.getHits()) {
    		result = hit.getSourceAsString();
    		    if (StringUtils.hasText(result)) {
    			e = JsonUtils.jsonToBean(result, clazz);
    		    }
    		    if (e != null) {
    			if (idField != null) {
    			    ReflectionUtils.setField(idField, e, hit.getId());
    			}
    			list.add(e);
    		    }
    	    }
    	}
    	return list;
    }
    
    public SearchRequestBuilder buildRequest(String indices, String type) {
	    return client.prepareSearch(indices).setTypes(type);
    }
    
    /**
     * 不存在就创建索引
     * 
     */
    public boolean createIndexIfNotExist(String index, String type) {
    	IndicesAdminClient adminClient = client.admin().indices();
    	IndicesExistsRequest request = new IndicesExistsRequest(index);
    	IndicesExistsResponse response = adminClient.exists(request).actionGet();
    	if (!response.isExists()) {
    	    return createIndex(index, type);
    	}
    	return true;
    }
    
    /**
     * 创建索引
     * 
     */
    public boolean createIndex(String index, String type) {
    	XContentBuilder mappingBuilder;
    	try {
    	    mappingBuilder = this.getMapping(type);
    	} catch (Exception e) {
    	    logger.error(String.format("创建Mapping 异常;index:%s type:%s,", index, type), e);
    	    return false;
    	}
    	Settings settings = Settings.builder().put("index.number_of_shards", 2)
    		.put("index.number_of_replicas", 1)
    		.put("index.refresh_interval", "5s").build();
    	IndicesAdminClient adminClient = client.admin().indices();
    	CreateIndexRequestBuilder builder = adminClient.prepareCreate(index);
    	builder.setSettings(settings);
    	CreateIndexResponse response = builder.addMapping(type, mappingBuilder).get();
    	logger.info("创建索引:{} 类型:{} 是否成功:{}", index, type, response.isAcknowledged());
    	return response.isAcknowledged();
    }
    
    /***
     * 创建索引的Mapping信息  注意声明的roles为nested类型
     */
    private XContentBuilder getMapping(String type) throws Exception {
    	XContentBuilder mappingBuilder = XContentFactory.jsonBuilder().startObject().startObject(type)
    		.startObject("_all").field("enabled", false).endObject()
    		.startObject("properties")
    			.startObject("userName").field("type", "keyword").endObject()
    			.startObject("age").field("type", "integer").endObject()
    			.startObject("birthday").field("type", "date").endObject()
    			.startObject("description").field("type", "text").field("analyzer", "ik_smart").endObject()
    			.startObject("roles").field("type", "nested")
    				.startObject("properties")
    					.startObject("createTime").field("type","date").endObject()
    					.startObject("name").field("type","keyword").endObject()
    					.startObject("description").field("type","text").field("analyzer", "ik_smart").endObject()
    				.endObject()
    			.endObject()
    		.endObject()
    	.endObject().endObject();
    	return mappingBuilder;
    }

}

3.3:编写service

@Service
public class OrgUserService implements StandardService,InitializingBean{

    @Autowired
    private ElasticOperationService elasticOperationService;
    
    private String index = "test-api";
    
    private String type = "user";
    
    
    @Override
    public void afterPropertiesSet() throws Exception {
	   elasticOperationService.createIndexIfNotExist(index, type);
    }
    
    
    public void batchAddUser(List<User> users) {
	   if(CollectionUtils.isEmpty(users)) {
	       return ;
	   }
	   for(User user :users) {
	       elasticOperationService.addDocumentToBulkProcessor(index, type, user);
	   }
    }
    
    
    @Override
    public void addUser(User user) {
	   elasticOperationService.addDocument(index, type, user);
    }

    @Override
    public void deletedUserById(String id) {
    	elasticOperationService.deleteDocumentById(index, type, id);
    }

    @Override
    public void updateUser(User user) {
	   String id = user.getId();
	   user.setId(null);
	   elasticOperationService.updateDocument(index, type,id, user);
    }

    @Override
    public List<User> queryByUserName(String userName) {
	
	   UserSearchParam param = new UserSearchParam();
	   param.setUserName(userName);
	   return elasticOperationService.queryDocumentByParam(index, type, param,User.class);
    }


    @Override
    public List<User> queryByRoleName(Role role) {
	   UserSearchParam param = new UserSearchParam();
	   param.setRoleName(role.getName());
	   return elasticOperationService.queryDocumentByParam(index, type, param,User.class);
    }

}

 

3.4:启动

@SpringBootApplication
public class DemoApplication {
    
    private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);
    
    public static void main(String[] args) {
	
	   SpringApplication.run(DemoApplication.class, args);
	   logger.info("start completed !");
    }
    
    
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值