java+Elasticsearch搜索引擎做增删改查操作(Springboot项目)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dfBeautifulLive/article/details/82868116

Elasticsearch查询搜索真的是非常快,所以企业数据量大的一般都存储到Elasticsearch里。用来分析,挖掘数据,

Elasticsearch的索引就相当于数据库,类型,就相当于表,文档就相当于数据库的row

索引-index
- 一个索引就是一个拥有几分相似特征的文档的集合
- 相当于数据库中的database

类型-type
- 一个类型是你的索引的一个逻辑上的分类/分区
- 通常,会为具有一组共同字段的文档定义一个类型
- 相当于数据库中的table

文档-document
- 一个文档是一个可被索引的基础信息单元
- 文档以JSON(Javascript Object Notation)格式来表示
- 相当于数据库中的row

分片-shard
- 一个分片是一个 Lucene 的实例,以及它本身就是一个完整的搜索引擎
- 一个索引可以有多个分片,必须在创建索引的时候指定分片数量,不能动态修改分片数量
- 多个分片主要是为了提高写入效率

副本-replicas
- 就是分片的副本,副本分片的主要目的就是为了故障转移
- 主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色
- 在索引写入时,新文档首先被索引进主分片然后再同步到其它所有的副本分片
- 副本分片可以服务于读请求,可以通过增加副本的数目来提升查询性能

废话少说,先实战吧

对了,一定要之前下载Elasticsearch,然后启动,才可以使用哦

首先引入Elasticsearch的依赖包,有很多不同的jar依赖,我目前就选择了jest客户端和transport客户端两种方式

 <dependency>
         <groupId>io.searchbox</groupId>
         <artifactId>jest</artifactId>
         <version>5.3.2</version>
  </dependency>

  <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>5.5.3</version>
 </dependency>
配置文件:
#jest连接方式需要的配置  配置elasticsearch
spring:
 elasticsearch:
  jest:
   uris:
   - http://127.0.0.1:9200
   read-timeout: 5000
#连接数据源
 datasource:
  url: jdbc:oracle:thin:@192.168.0.86:1521:ORCL86
  username: exdb_guotu
  password: exdb_guotu
  driver-class-name: oracle.jdbc.driver.OracleDriver
  nitialSize: 5
  maxWait: 60000
  minIdle: 5
transport连接方式,配置,写在代码里,不用transport可以不用这段代码 
package com.config;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.stereotype.Component;

import java.net.InetAddress;

/**
 * Created by df on 2018/9/19.
 */
@Component
public class TransportClientUitl {
    private TransportClient transportClient;
    //transportClient的加载配置
    public TransportClient getClient() throws Exception{
        //设置集群名称
        Settings settings = Settings.builder().put("cluster.name", "df-elaticSearch").build();// 集群名
        //集群名称就是我们Elasticsearch的名称,我的是我自己起的
        //创建client
        transportClient  = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        return transportClient;
    }
}

先来个测试,添加个实体,实体里边放索引和类型,还有存储的字段

package com.entity;

/**
 * Created by df on 2018/9/17.
 */
public class entity {

    public static final String INDEX_NAME = "df_index";//相当于数据库名称

    public static final String TYPE = "df_tstype";//相当于表名

    private String key;
    private String Value;

    public entity(){
        super();
    }
    public entity(String key,String Value){
        this.key=key;
        this.Value=Value;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return Value;
    }

    public void setValue(String value) {
        Value = value;
    }
}

然后就可以对Elasticsearch做增删改查了  

package com.service;

import com.config.TransportClientUitl;
import com.entity.entity;
import com.sqlSource.SqlHadle;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.*;

import io.searchbox.indices.DeleteIndex;
import io.searchbox.indices.mapping.GetMapping;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;


import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created by df on 2018/9/17.
 */
@Service
public class testServiceImpl implements testService {
    private static final Logger LOGGER = LoggerFactory.getLogger(testServiceImpl.class);
    @Autowired
    private JestClient jestClient;

    /**
     * 插入单个数据
     */
    @Override
    public void saveEntity(entity en) {
        Index index = new Index.Builder(en)
                .index(entity.INDEX_NAME).type(entity.TYPE).build();
        try {
            jestClient.execute(index);
            LOGGER.info("ES 插入完成");
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage());
        }
    }

    SqlHadle sqlHadle = new SqlHadle();

   /**
     * 批量插入多个
     * index  索引名(数据库名)
     * type   类型(表)
     */
    @Override
    public void insertBatch(String index, String type) {
        //从数据库查询出来的数据 然后在存储到Elasticsearch里
        List<Map<String, Object>> entityList = sqlHadle.queryTest();
        long startTime = System.currentTimeMillis();
        boolean result = false;
        try {
            //Bulk方式
            Bulk.Builder bulk = new Bulk.Builder().defaultIndex(index).defaultType(type);
            for (Map map : entityList) {
                Index index1 = new Index.Builder(map).build();
                bulk.addAction(index1);
            }
            BulkResult br = jestClient.execute(bulk.build());
            result = br.isSucceeded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("批量新增:" + result + " 消耗了" + (endTime - startTime) + "ms");
    }

 /**
     * 查询某一个字段
     * searchContent 查询的属性值
     * key           字段名称
     */
    @Override
    public List<entity> searchEntity(String searchContent, String key) {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchQuery(key, searchContent));
        Search search = new Search.Builder(builder.toString()).addIndex(entity.INDEX_NAME)
                .addType(entity.TYPE).build();
        try {
            JestResult result = jestClient.execute(search);
            return result.getSourceAsObjectList(entity.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

   /**
     * 删除某个id下的文档,想知道id可以去Elasticsearch的共工具里看,也可以用程序获取
     * id      文档id
     * index  索引名(数据库名)
     * type   类型(表)
     */
    @Override
    public void deleteDoc(String id, String index, String type) {
        Delete delete = new Delete.Builder(id).index(index).type(type).build();
        JestResult result = null;
        try {
            result = jestClient.execute(delete);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

  /**
     * 删除某个索引
     * index  索引名(数据库名)
     */
    @Override
    public void deleteIndex(String index) {
        DeleteIndex deleteIndex = new DeleteIndex.Builder(index).build();
        JestResult result = null;
        try {
            result = jestClient.execute(deleteIndex);
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

  /**
     * 查询所有  结果Elasticsearch默认只能查出10条,最多的size也只能10000条
     * index  索引名(数据库名)
     * type   类型(表)
     */
    @Override
    public void searchAll(String index, String type) {
        GetMapping getMapping = new GetMapping.Builder().addIndex(index)
                .addType(type).build();
        try {
            JestResult jr = jestClient.execute(getMapping);
            System.out.println(jr.getJsonString());
        } catch (IOException e) {
            e.printStackTrace();
        }

//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.query(QueryBuilders.matchAllQuery());
//        Search search = new Search.Builder(sourceBuilder.toString()).addIndex("df_index").build();
//        SearchResult result = null;
//        List his = null;
//        try {
//            result = jestClient.execute(search);
//            System.out.println("本次查询共查到:" + result.getTotal() + "个关键字!");
//            his = result.getHits(Object.class);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return his;
    }

  /**
     * 全文搜索  根据某个字段全篇搜索
     * indexName  索引名(数据库名)
     * typeName  类型(表)
     * query     字段
     * query数据是这种格式
     * query="{\n" +
     "  \"from\" : 0,\n" +
     "  \"size\" : 9999,\n" +
     "  \"query\" : {\n" +
     "    \"query_string\" : {\n" +
     "      \"query\" : \"惠州\"\n" +
     "    }\n" +
     "  }\n" +
     "}\n";
     */
    @Override
    public String search(String indexName, String typeName, String query) {
        long startTime = System.currentTimeMillis();
        Search search = new Search.Builder(query).addIndex(indexName).addType(typeName).build();
        JestResult jr = null;
        try {
            jr = jestClient.execute(search);
            long endTime = System.currentTimeMillis();
            System.out.println("Elasticsearch中查询消耗:" + (endTime - startTime) + "ms");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jr.getJsonString();
    }


    @Autowired
    private TransportClientUitl clientUitl;

    /**
     * 滚动分页,采用的是TransportClient客户端方式操作
     * 这个滚动分页其实是查询索引里的全部数据,这个效率最高,最快,每一次滚动设置查询多少页,
     * 然后下一次找到这一次记录的id然后继续滚动,直至数据都没有为止
     * 采用条件:数据量大,
     * query    查询需要的配置,如下query变量所示
     * indexName  索引名(数据库名)
     * typeName  类型(表)
     */
   String  query= "\"{\" +\n"+
            "            \"    \\\"query\\\":{\" +\n"+
            "            \"        \\\"match\\\":{\\\"srv_content\\\":\\\"google\\\"}}\" +\n"+
            "            \"    }\" +\n"+
            "            \"}\"";
    public void searchScroll(String query, String indexName, String typeName) {
        long startTime = System.currentTimeMillis();
        try {
            SearchRequestBuilder searchBuilder = clientUitl.getClient().prepareSearch(indexName);
            searchBuilder.setTypes(typeName);
            //设置每批读取的的数据量
            searchBuilder.setSize(10000);
            //默认是查询所有
            searchBuilder.setQuery(QueryBuilders.queryStringQuery("*:*"));
            //设置 search context 维护1分钟的有效期
            searchBuilder.setScroll(TimeValue.timeValueMillis(3));
            //获得首次查询结果
            SearchResponse searchResponse = searchBuilder.get();
            System.out.println("命中总数量:" + searchResponse.getHits().getTotalHits());
            //打印计数
            int count = 1;

            do {
                System.out.println("第" + count + "次打印数据:");
                for (SearchHit hit : searchResponse.getHits().getHits()) {
                   // System.out.println(hit.getSource());
                }
                count++;
                //将scorllId循环传递
                searchResponse=clientUitl.getClient().prepareSearchScroll(searchResponse.getScrollId())
                        .setScroll(TimeValue.timeValueMillis(1)).execute().actionGet();
                //当searchHits的数组为空的时候结束循环,至此数据全部读取完毕
            } while (searchResponse.getHits().getHits().length != 0);
            long endTime = System.currentTimeMillis();
            System.out.println("Elasticsearch中查询所有的数据消耗:" + (endTime - startTime) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



}

对Elasticsearch做基本的增删改查就弄好了,附赠两个Elasticsearch做完操作的图片

猜你喜欢

转载自blog.csdn.net/dfBeautifulLive/article/details/82868116