springboot集成Elasticsearch 简单应用

概念

索引(Index):索引库,一个Elasticsearch可以有多个索引库 (相当于 mysql 创建的数据库)
类型(Type):分组,一个索引库可以有多个分组 (相当于 mysql 的数据表)
文档(Document):相当于mysql数据表中的每一行数据
字段(Fields):相当于 mysql 字段名称
mapping:相当于 mysql 的表结构

下载并安装 Elasticsearch

参考 https://blog.csdn.net/yjclsx/article/details/81302041

基本用法

Elasticsearch调用都是遵循restful风格方式进行调用。
详细参考https://www.cnblogs.com/swordfall/p/8923087.html

集成springboot

pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<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.1.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.elasticsearch</groupId>
	<artifactId>elasticsearch</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>elasticsearch</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RC1</spring-cloud.version>
		<sharding.jdbc.version>3.0.0</sharding.jdbc.version>
		<druid.version>1.1.6</druid.version>
	</properties>

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

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>



		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>elasticsearch-rest-high-level-client</artifactId>
			<version>6.2.1</version>
		</dependency>

		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>transport</artifactId>
			<version>6.2.1</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>${druid.version}</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.29</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>${spring_boot.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://maven.aliyun.com/repository/public</url>
		</repository>
	</repositories>

</project>

配置连接Elasticsearch

package com.elasticsearch.constants;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;

@Configuration
public class ElasticsearchContants {

    @Bean
    public TransportClient initElasticsearch() {
        TransportClient transportClient = null;
        try {
            // 配置信息
            Settings esSetting = Settings.builder()
                    .put("cluster.name", "elasticsearch") //集群名字
                    .put("thread_pool.search.size", Integer.parseInt("5"))//增加线程池个数,暂时设为5
                    .build();
            //配置信息Settings自定义
            transportClient = new PreBuiltTransportClient(esSetting);
            TransportAddress transportAddress = new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300);
            transportClient.addTransportAddresses(transportAddress);
        } catch (Exception e) {

        }
        return transportClient;
    }
}

工具类

package com.elasticsearch.utils;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.elasticsearch.constants.ElasticsearchContants;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class ElasticsearchUtils {

    @Autowired
    private ElasticsearchContants elasticsearchContants;

    private static TransportClient client;

    @PostConstruct
    private void init(){
        client = elasticsearchContants.initElasticsearch();
    }

    /**
     * 创建索引库
     *
     * @param index
     * @return
     */
    public static boolean createIndex(String index) {
        if(isIndexExist(index)){
            return true;
        }
        CreateIndexResponse createIndexResponse = client.admin().indices().prepareCreate(index).execute().actionGet();
        return createIndexResponse.isAcknowledged();
    }
    
	/**
     * 创建复杂索引,包括初始化类型,mapping
     * @param index
     * @param type
     * @param mapping  类似json数据字符串
     * @return
     */
    public static boolean createIndex(String index, String type, XContentBuilder mapping){
        if(isIndexExist(index)){
            return true;
        }
        //umber_of_replicas 是数据备份数,如果只有一台机器,设置为0
        //number_of_shards  是数据分片数,默认为5,有时候设置为3
        Settings settings = Settings.builder().put("index.number_of_shards", 3)
                .put("index.number_of_replicas", 0).build();
        PutMappingResponse putMappingResponse = client.admin().indices()
                .preparePutMapping(index)
                .setType(type)// setting
                .setSource(mapping)// type,mapping
                .get();
        return putMappingResponse.isAcknowledged();

    }

    /**
     * 删除索引库
     * @param index
     * @return
     */
    public static boolean delIndex(String index) {
        if(!isIndexExist(index)){
            return true;
        }
        AcknowledgedResponse acknowledgedResponse = client.admin().indices().prepareDelete(index).execute().actionGet();
        return acknowledgedResponse.isAcknowledged();
    }

    /**
     * 索引库是否存在
     * @param index
     * @return
     */
    public static boolean isIndexExist(String index){
        IndicesExistsResponse indicesExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet();
        return indicesExistsResponse.isExists();
    }

    /**
     * 数据添加,id自定义
     * @param jsonObject
     * @param index
     * @param type
     * @param id
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type, String id){
        IndexResponse indexResponse = client.prepareIndex(index, type, id).setSource(jsonObject).get();
        return indexResponse.getId();
    }

    /**
     * 数据添加,id默认
     * @param jsonObject
     * @param index
     * @param type
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type){
        IndexResponse indexResponse = client.prepareIndex(index, type).setSource(jsonObject).get();
        return indexResponse.getId();
    }

    /**
     * 通过 index,type,id 删除数据
     * @param index
     * @param type
     * @param id
     */
    public static void delDataById(String index, String type,String id){
        client.prepareDelete(index, type, id).execute().actionGet();
    }

    /**
     * 通过 index,type,id 修改数据
     * @param index
     * @param type
     * @param id
     */
    public static void updateDataById(JSONObject jsonObject,String index, String type,String id){
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.index(index).type(type).id(id).doc(jsonObject);
        ActionFuture<UpdateResponse> update = client.update(updateRequest);
    }

    /**
     * 通过 index,type,id 查询数据
     * @param index
     * @param type
     * @param id 需要显示的字段,逗号分隔(不传则展示全部字段)
     */
    public static Map<String, Object> queryDataById(String index, String type, String id, String fields){
        GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);
        if(!StringUtils.isEmpty(fields)){
            getRequestBuilder.setFetchSource(fields.split(","),null);
        }
        GetResponse documentFields = getRequestBuilder.execute().actionGet();
        return documentFields.getSource();
    }

    /**
     *
     * @param index
     * @param type  类型名称,可传入多个type逗号分隔
     * @param query   查询条件
     * @param size  需要查询出多少条结果
     * @param fields 需要显示的字段,逗号分隔(不传则展示全部字段)
     * @param sortField 排序字段
     * @param sortType 排序方式 asc desc
     * @return
     */
    public static List<Map<String, Object>> searchDataList(String index, String type, QueryBuilder query, Integer size, String fields, String sortField,  SortOrder sortType){
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
        //设置查询的 type
        if (!StringUtils.isEmpty(type)) {
            searchRequestBuilder.setTypes(type.split(","));
        }
        //设置查询条件
        searchRequestBuilder.setQuery(query);
        if (!StringUtils.isEmpty(fields)) {
            searchRequestBuilder.setFetchSource(fields.split(","),null);
        }
        searchRequestBuilder.setFetchSource(true);
        //设置排序
        if (!StringUtils.isEmpty(sortField)) {
            searchRequestBuilder.addSort(sortField, sortType);
        }
        //文档大小限制
        if(size != null && size > 0){
            searchRequestBuilder.setSize(size);
        }

        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

        //共查询的数据数量
        long totalSize = searchResponse.getHits().totalHits;
        //处理的数据数量
        long dealSize = searchResponse.getHits().totalHits;
        System.out.println("共查询到[" + totalSize + "]条数据,处理数据条数[" + dealSize + "]");
        if (searchResponse.status().getStatus() == 200) {
            return setSearchResponse(searchResponse);
        }
        return null;
    }

    /**
     * 将查询结果返回为list<Map>
     * @param searchResponse
     * @return
     */
    private static List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse){
        List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>();
        StringBuffer stringBuffer = new StringBuffer();

        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
            searchHit.getSourceAsMap().put("id", searchHit.getId());
            sourceList.add(searchHit.getSourceAsMap());
        }

        return sourceList;
    }
}

编写测试类

import com.alibaba.fastjson.JSONObject;
import com.elasticsearch.ElasticsearchApplication;
import com.elasticsearch.constants.ElasticsearchContants;
import com.elasticsearch.utils.ElasticsearchUtils;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = ElasticsearchApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class TestJava {

    @Autowired
    ElasticsearchContants elasticsearchContants;

    @Test
    public void elasticsearchTest(){

		//新增 test 索引库
		ElasticsearchUtils.createIndex("test");
		//新增分组 user,并添加数据,id自己生成
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name","李四1");
        jsonObject.put("city","北京1");
        jsonObject.put("age","111");
        jsonObject.put("desc","这是李四的描述1");
        ElasticsearchUtils.addData(jsonObject,"test","user","1");
        //新增分组 user,并添加数据,id默认生成
        jsonObject = new JSONObject();
        jsonObject.put("name","王五");
        jsonObject.put("city","上海");
        jsonObject.put("age","21");
        jsonObject.put("desc","王五就是我,我就是隔壁老王");
        ElasticsearchUtils.addData(jsonObject,"test","user");
        //根据id删除
        // ElasticsearchUtils.delDataById("test","user","1");
        //修改id为1的用户信息
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name","李四");
        jsonObject.put("city","北京");
        jsonObject.put("age","11");
        jsonObject.put("desc","这是李四的描述");
        ElasticsearchUtils.updateDataById(jsonObject,"test","user","1");
      	//查询id为1 的用户姓名
        System.out.println(JSONObject.toJSON(ElasticsearchUtils.queryDataById("test","user","1","name")).toString());


        //打印结果   [{"name":"王五","id":"8vIqC3QBsN7wCGyBOPw6","city":"上海","age":"21","desc":"王五就是我,我就是隔壁老王"}]
        QueryBuilder queryBuilder = QueryBuilders.commonTermsQuery("name","王");
        System.out.println(JSONObject.toJSON(ElasticsearchUtils.searchDataList("test","user",queryBuilder,null,null,null, null)));

        //打印结果   [{"name":"王五","id":"8vIqC3QBsN7wCGyBOPw6","city":"上海","age":"21","desc":"王五就是我,我就是隔壁老王"}]
        QueryBuilder queryBuilder1 = QueryBuilders.commonTermsQuery("name","王五");
        System.out.println(JSONObject.toJSON(ElasticsearchUtils.searchDataList("test","user",queryBuilder1,null,null,null, null)));

        //打印结果  [{"name":"王五","city":"上海","id":"8vIqC3QBsN7wCGyBOPw6"},{"name":"李四","city":"北京","id":"1"}]
        QueryBuilder queryBuilder2 = QueryBuilders.commonTermsQuery("desc","就是");
        System.out.println(JSONObject.toJSON(ElasticsearchUtils.searchDataList("test","user",queryBuilder2,100,"name,city",null, null)));
    }
}

注意

测试类中查询时用到的 QueryBuilders.commonTermsQuery 只是其中一种查询方式,其他用法参考 https://www.cnblogs.com/xiang–liu/p/11498367.html

可能出现的错误

在这里插入图片描述
如上图所示错误,出现原因为连接Elasticsearch错误。没启动,集群名称或者端口号写错了等。要按照配置文件来写。
但是要注意我配置的端口号为9200,但是连接9200 会报错,需要写成9300。9200作为Http协议,主要用于外部通讯。9300作为集群通讯。上面的配置方式是集群方式,虽然只有一个节点,但是也要用9300端口。

我用上面代码,给name字段排序,然后出现错误。原因 Elasticsearch 默认只支持数字和日期排序;
如果要实现,给索引设置mapping,将排序字段配置成 fielddata:true也可以支持。

ElasticsearchUtils.createIndex("test_1","user_1",getMappering())
private XContentBuilder getMappering(){
        XContentBuilder builder = null;
        try {
            //{"user_1" : {"properties" : {"age" : { "type" : "long"},"city" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}},"fielddata":true},"name" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"desc" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}}}}}
            builder= XContentFactory.jsonBuilder()
                    .startObject().startObject("user_1").startObject("properties").
                            startObject("age").field("type","long").endObject().
                            startObject("city").field("type","text").field("fielddata","true").endObject().
                            startObject("name").field("type","text").endObject()
            .endObject().endObject().endObject();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return builder;
    }

调用此方法可设置mapping

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值