Elasticsearch搜索引擎

Elasticsearch搜索引擎

介绍

Elasticsearch是一个实时的分布式搜索分析引擎,底层基于Lucene实现。它提供了一个分布式多用户能力的全文搜索引擎,并且客户端可以使用标准的RESTful进行访问。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
传统的搜索做法主要以是基于系统或应用的查询功能进行查找,或者使用数据库的模糊查询等机制来完成。这些方式相对简单,对于少量数据来说操作性比较方便。但对于海量数据,性能就会急剧下降导致不能及时响应,且不易于扩展。而使用搜索引擎的好处在于,它可以存储非结构化的数据,进行相关的排序、过滤以及分词等功能,快速检索我们需要的数据信息。

可以从官网下载最新版本: https://www.elastic.co/cn/products/

image-20190418162819393

使用

Maven

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

案例

EsClientUtils

public class EsClientUtils {

    private static String host = "127.0.0.1";
    private static Integer port = 9200;

    public static RestHighLevelClient getClient() {
        RestClientBuilder builder = RestClient
                .builder(new HttpHost(host, port));
        return new RestHighLevelClient(builder);
    }
}

IndexDemo

操作index

public class IndexDemo {

    /**
     * 创建索引
     * @param index
     */
    public void createIndex(String index) {
        try(RestHighLevelClient client = EsClientUtils.getClient()){
            //构建创建索引的请求对象
            CreateIndexRequest request = new CreateIndexRequest(index);
            //通过客户端发送请求到es完成创建,并返回一个响应对象
            CreateIndexResponse response = client.indices()
                    .create(request, RequestOptions.DEFAULT);
            //输出ack是否创建成功
            String ack = response.isAcknowledged() ? "创建成功": "创建失败";
            log.info(ack);
        }catch(Exception e) {
            throw new RuntimeException("创建索引失败", e);
        }
    }

    /**
     * 删除索引
     * @param index
     */
    public void deleteIndex(String index) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            //创建删除索引请求
            DeleteIndexRequest request = new DeleteIndexRequest(index);
            //发送请求并返回响应对象
            AcknowledgedResponse response = client.indices()
                    .delete(request, RequestOptions.DEFAULT);
            //输出ack是否删除成功
            String ack = response.isAcknowledged() ? "删除成功": "删除失败";
            log.info(ack);
        }catch(Exception e) {
            throw new RuntimeException("删除索引失败", e);
        }
    }

    /**
     * 关闭索引
     * @param index
     */
    public void closeIndex(String index) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            //创建关闭索引的请求对象
            CloseIndexRequest request = new CloseIndexRequest(index);
            //发送请求并返回响应对象
            CloseIndexResponse response = client.indices()
                    .close(request, RequestOptions.DEFAULT);
            String ack = response.isAcknowledged() ? "关闭成功" : "关闭失败";
            log.info(ack);
        }catch (Exception e) {
            throw new RuntimeException("关闭索引失败", e);
        }
    }

    /**
     * 打开索引
     * @param index
     */
    public void openIndex(String index) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            OpenIndexRequest request = new OpenIndexRequest(index);
            OpenIndexResponse response = client.indices()
                    .open(request, RequestOptions.DEFAULT);
            String ack = response.isAcknowledged() ? "打开成功" : "打开失败";
            log.info(ack);
        }catch (Exception e) {
            throw new RuntimeException("打开索引失败", e);
        }
    }

    /**
     * 为指定的index创建mappings
     * @param index
     */
    public void createMapping(String index) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            //创建一个构建mapping的请求对象
            PutMappingRequest request = new PutMappingRequest(index);
            //使用XContentBuilder来构建mapping
            XContentBuilder builder = XContentFactory.jsonBuilder();
            builder.startObject();
            {
                builder.startObject("properties");
                {
                    //name属性
                    builder.startObject("name");
                    {
                        //设置字段类型
                        builder.field("type", "keyword");
                    }
                    builder.endObject();
                    //age属性
                    builder.startObject("age");
                    {
                        builder.field("type", "integer");
                    }
                    builder.endObject();
                    //birthplace属性
                    builder.startObject("birthplace");
                    {
                        builder.field("type", "text");
                        builder.field("analyzer", "ik_max_word");
                    }
                    builder.endObject();
                }
                builder.endObject();
            }
            builder.endObject();
            //将builder设置到请求对象中
            request.source(builder);
            //发送请求并返回响应
            AcknowledgedResponse response = client.indices()
                    .putMapping(request, RequestOptions.DEFAULT);
            String ack = response.isAcknowledged() ? "创建成功" : "创建失败";
            log.info(ack);
        }catch (Exception e) {
            throw new RuntimeException("创建mappings失败", e);
        }
    }
}

DocumentDemo

操作文档

public class DocumentDemo {

    /**
     * 创建文档
     * @param index 索引
     * @param id 唯一标识
     * @param map map数据集合
     */
    public void createDoc(String index, String id,
                          Map<String, Object> map) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            //创建IndexRequest请求对象
            IndexRequest request = new IndexRequest(index)
                    .id(id).source(map);
            //发送请求并返回响应对象
            IndexResponse response = client
                    .index(request, RequestOptions.DEFAULT);
            String docId = response.getId();
            log.info("文档ID:" + docId);
        }catch (Exception e) {
            throw new RuntimeException("创建文档失败", e);
        }
    }

    /**
     * 根据id查找文档
     * @param index
     * @param id
     * @return
     */
    public Map<String, Object> getDocById(String index,
                                          String id) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            GetRequest request = new GetRequest(index, id);
            GetResponse response = client.get(request,
                    RequestOptions.DEFAULT);
            return response.getSource();
        }catch (Exception e) {
            throw new RuntimeException("查找文档失败", e);
        }
    }

    /**
     * 全文检索
     * @param index 索引
     * @param field 搜索的字段
     * @param params 查询参数
     * @return
     */
    public List<Map<String, Object>> search(String index,
                                            String field,
                                            String params) {
        try(RestHighLevelClient client = EsClientUtils.getClient()) {
            //创建搜索的请求对象
            SearchRequest request = new SearchRequest(index);
            //创建检索器,创建检索的条件和类型
            SearchSourceBuilder builder = new SearchSourceBuilder();
            //通过QueryBuilder创建不同的检索类型(term、match、bool)
            //并传入字段和查询参数,这里使用的是布隆查询器
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            //设置查询参数,使用should子查询结合match检索
            queryBuilder.should(QueryBuilders.matchQuery(field, params));
            //将布隆查询器设置给SearchSourceBuilder
            builder.query(queryBuilder);
            //将builder设置到请求对象中
            request.source(builder);
            //发送请求进行检索并返回响应对象
            SearchResponse response = client.search(request,
                    RequestOptions.DEFAULT);
            //从SearchResponse中获取命中的检索记录
            SearchHits hits = response.getHits();
            List<Map<String, Object>> results = new ArrayList<>();
            hits.forEach(hit -> {
                //将每一条命中的记录转换为map集合并放入list中
                results.add(hit.getSourceAsMap());
            });
            return results;
        }catch (Exception e) {
            throw new RuntimeException("检索失败", e);
        }
    }
}