SpringBoot-ElasticSearch5.6.8操作

x33g5p2x  于2021-09-24 转载在 Spring  
字(39.8k)|赞(0)|评价(0)|浏览(620)

使用IDEA创建elasticsearch-study Maven工程

添加Maven

<dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

创建索引index

//创建索引
   @org.junit.Test
    public void test1() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
        //创建名称为blog2的索引
        client.admin().indices().prepareCreate("blog2").get();
        //释放资源
        client.close();
    }

在运行前 先把集群打开 保证没有什么问题

然后运行java代码

我们查看 elasticsearch-head

可以发现索引添加成功了

创建映射mapping

有索引才能创建 mapping 映射 否则失败

//创建映射
    @org.junit.Test
    public void test3() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

       //创建表的格式
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("article")  //指定article表
                .startObject("properties") //给article表添加字段
                //创建字段id 添加字段格式
                .startObject("id").field("type", "integer").field("store", "yes").endObject()
                //创建字段title 添加字段格式
                .startObject("title").field("type", "string").field("store", "yes").field("analyzer", "ik_smart").endObject()
                //创建字段content 添加字段格式
                .startObject("content").field("type", "string").field("store", "yes").field("analyzer", "ik_smart").endObject()
                .endObject()  //结束第一个startObject
                .endObject()  //结束第二个startObject
                .endObject();//结束第三个startObject

        // 创建映射blog2(必须保证blog2索引存在) 和给这个索引添加表article 然后将上面定义好的表格式 传递给表article
        PutMappingRequest mapping = Requests.putMappingRequest("blog2")
                .type("article").source(builder);
        client.admin().indices().putMapping(mapping).get();
        //释放资源
        client.close();
    }

建立文档document

必须保证 有 索引 和 类型(表) 的存在 以及给表进行mapping之后 才能进行 添加数据(文档)

//创建文档(通过XContentBuilder)
    @org.junit.Test
    public void test4() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        //创建文档信息
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()//开始
                .field("id", 1) //给字段id 赋值
                .field("title", "ElasticSearch是一个基于Lucene的搜索服务器")  //给字段title 赋值
                .field("content",
                        "它提供了一个分布式多用户能力的全文搜索引擎," +
                                "基于RESTful web接口。Elasticsearch是用Java开发的," +
                                "并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。" +
                                "设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。")//给字段content赋值
                .endObject();//结束

        // 建立文档对象
        /** * 参数一blog1:表示索引对象 * 参数二article:类型(表) * 参数三1:建立文档id ( 行对应的行号) */
        client.prepareIndex("blog2", "article", "1").setSource(builder).get();

        //释放资源
        client.close();
    }

建立文件的documend(实体类方式)

必须保证 有 索引 和 类型(表) 的存在 以及给表进行mapping之后 才能进行 添加数据(文档)

使用Jackson转换实

需要的Maven

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.8</version>
        </dependency>

创建一个实体类

public class Article {

    private Integer id;
    private String title;
    private String content;
..... get set
}

添加文档(一条数据)

//创建文档(通过实体转json)
    @org.junit.Test
    public void test5() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        // 给实体类赋值
        Article article = new Article();
        article.setId(2);  //文档id 同时也作为 字段id
        article.setTitle("搜索工作其实很快乐");
        article.setContent("我们希望我们的搜索解决方案要快," +
                "我们希望有一个零配置和一个完全免费的搜索模式," +
                "我们希望能够简单地使用JSON通过HTTP的索引数据," +
                "我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百," +
                "我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。" +
                "Elasticsearch旨在解决所有这些问题和更多的问题。");

        //需要导入的包 import com.fasterxml.jackson.databind.ObjectMapper;
        ObjectMapper objectMapper = new ObjectMapper();

        // 建立文档 给blog索引 中article表内添加 一行数据
        client.prepareIndex("blog2", "article", article.getId().toString())
                //将实体类的内容转换为json格式 写入表中
                .setSource(objectMapper.writeValueAsString(article).getBytes(), XContentType.JSON).get();

        //释放资源
        client.close();
    }

查询文档term查询

查询指定表内所有指定字段内容 是否满足查询条件 满足就返回哪一行数据

注意 依据分词查询 通常用于数字,日期和枚举等结构化数据,

@org.junit.Test
    public void testTermQuery() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        //2、设置搜索条件
        SearchResponse searchResponse = client.prepareSearch("blog2")//要查询的索引
                //要查询的表
                .setTypes("article")
                //要查询的字段 和要查询的值
                .setQuery(QueryBuilders.termQuery("content", "搜索")).get();

        //3、遍历搜索结果数据
        SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
        System.out.println("查询结果有:" + hits.getTotalHits() + "条");
        Iterator<SearchHit> iterator = hits.iterator();
        while (iterator.hasNext()) {
            SearchHit searchHit = iterator.next(); // 每个查询对象
            System.out.println(searchHit.getSourceAsString()); // 打印每个查询出来的行
            System.out.println("title:" + searchHit.getSource().get("title"));//查询每行指定字段
        }
        //4、释放资源
        client.close();
    }

查询文档query_string查询

查询指定表内所有 内容 是否满足查询条件 满足就返回哪一行数据

以分词进行 匹配查询 通常用于文档匹配 标题匹配 … 等

@org.junit.Test
    public void testStringQuery() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        //2、设置搜索条件
        SearchResponse searchResponse = client.prepareSearch("blog2")//查询的索引
                .setTypes("article")//查询的表
                //需要查询的内容
                .setQuery(QueryBuilders.queryStringQuery("搜索")).get();

        //3、遍历搜索结果数据
        SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
        System.out.println("查询结果有:" + hits.getTotalHits() + "条");
        Iterator<SearchHit> iterator = hits.iterator();
        while (iterator.hasNext()) {
            SearchHit searchHit = iterator.next(); // 每个查询对象
            System.out.println(searchHit.getSourceAsString()); // 打印每个查询出来的行
            System.out.println("title:" + searchHit.getSource().get("title"));//查询每行指定字段
        }

        //4、释放资源
        client.close();

    }

使用文档ID查询文档

@org.junit.Test
    public void testIdQuery() throws Exception {
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        //client对象为TransportClient对象
        SearchResponse response = client.prepareSearch("blog2")//要查询的索引
                .setTypes("article")//要查询的表
                //要查询的id
                .setQuery(QueryBuilders.idsQuery().addIds("2"))
                //执行查询
                .get();
        //3、遍历搜索结果数据
        SearchHits hits = response.getHits(); // 获取命中次数,查询结果有多少对象
        System.out.println("查询结果有:" + hits.getTotalHits() + "条");
        Iterator<SearchHit> iterator = hits.iterator();
        while (iterator.hasNext()) {
            SearchHit searchHit = iterator.next(); // 每个查询对象
            System.out.println(searchHit.getSourceAsString()); // 打印每个查询出来的行
            System.out.println("title:" + searchHit.getSource().get("title"));//查询每行指定字段
        }

        //4、释放资源
        client.close();
    }

查询文档分页操作

在查询前我们需要有大量的数据

批量插入数据

@org.junit.Test
//批量插入100条数据
    public void test9() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        ObjectMapper objectMapper = new ObjectMapper();

        for (int i = 1; i <= 100; i++) {
            // 描述json 数据
            Article article = new Article();
            article.setId(i);
            article.setTitle(i + "搜索工作其实很快乐");
            article.setContent(i
                    + "我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。");

            // 建立文档 向blog2索引中article表插入数据
            client.prepareIndex("blog2", "article", article.getId().toString())
                    //.setSource(objectMapper.writeValueAsString(article)).get();
                    .setSource(objectMapper.writeValueAsString(article).getBytes(),XContentType.JSON).get();
        }

        //释放资源
        client.close();
    }

分页查询

就和mysql数据库 分页一样效果

@org.junit.Test
//分页查询
    public void test10() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        // 搜索数据 查询blog2索引下面article表的所有内容 进行分页---
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2").setTypes("article")
                .setQuery(QueryBuilders.matchAllQuery());  //默认显示0-10条

        // 设置setFrom和setSize 后上面默认显示失效 按照我们自己的规则来显示
        //setFrom():从第几条开始检索,默认是0。
        //setSize():每页最多显示的记录数。
        searchRequestBuilder.setFrom(0).setSize(5);   //显示 0-5条数据

        SearchResponse searchResponse = searchRequestBuilder.get();

        SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
        System.out.println("查询结果有:" + hits.getTotalHits() + "条");
        Iterator<SearchHit> iterator = hits.iterator();
        while (iterator.hasNext()) {
            SearchHit searchHit = iterator.next(); // 每个查询对象
            System.out.println(searchHit.getSourceAsString()); // 打印每个查询出来的行
            System.out.println("id:" + searchHit.getSource().get("id"));//查询每行指定字段
            System.out.println("title:" + searchHit.getSource().get("title"));//查询每行指定字段
            System.out.println("content:" + searchHit.getSource().get("content"));//查询每行指定字段
            System.out.println("-----------------------------------------");
        }

        //释放资源
        client.close();
    }

查询结果高亮操作

什么是高亮

在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮

ElasticSearch可以对查询出的内容中关键字部分进行标签和样式的设置,但是你需要告诉ElasticSearch使用什么标签对高亮关键字进行包裹

高亮显示代码实现

@org.junit.Test
//高亮查询
    public void test11() throws Exception{
        // 创建Client连接对象 就是你在elasticsearch.yml配置文件里设置的集群名称 cluster.name: my-elasticsearch
        Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
        //连接 127.0.0.1:9300 这个集群中指定的节点 而不是9200了 节点的端口号可以在 elasticsearch-head->信息->节点状态里查看
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

        // 搜索数据
        SearchRequestBuilder searchRequestBuilder = client
                //查询blog2 中的article表内的title字段 中分词满足 搜索的行
                .prepareSearch("blog2").setTypes("article")
                .setQuery(QueryBuilders.termQuery("title", "搜索"));

        //设置高亮数据
        HighlightBuilder hiBuilder=new HighlightBuilder();
        hiBuilder.preTags("<font style='color:red'>"); //包裹需要高亮的 开始标签
        hiBuilder.postTags("</font>");//包裹需要高亮的 结束标签
        hiBuilder.field("title"); //要和termQuery指定查询的字段一致
        searchRequestBuilder.highlighter(hiBuilder);  //将高亮添加到内容里

        //获得查询结果数据
        SearchResponse searchResponse = searchRequestBuilder.get();

        //获取查询结果集
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("共搜到:"+searchHits.getTotalHits()+"条结果!");
        //遍历结果
        for(SearchHit hit:searchHits){
            System.out.println("String方式打印文档搜索内容:");
            System.out.println(hit.getSourceAsString());
            System.out.println("---------------------------------------------");
            System.out.println("Map方式打印高亮内容");
            System.out.println(hit.getHighlightFields());

            System.out.println("---------------------------------------------");
            System.out.println("遍历高亮集合,打印高亮片段:");
            //需要导入 import org.elasticsearch.common.text.Text;
            Text[] text = hit.getHighlightFields().get("title").getFragments();
            for (Text str : text) {
                System.out.println(str);
            }
            System.out.println("\n\n");
        }

        //释放资源
        client.close();
    }

SpringDataElasticSearch 使用

介绍

Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。

Spring Data的官网:http://projects.spring.io/spring-data/

什么是Spring Data ElasticSearch

Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。

官方网站:http://projects.spring.io/spring-data-elasticsearch/

SpringDataElasticSearch入门

导入Spring Data ElasticSearch的Maven

<dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.8</version>
        </dependency>

<!--Spring Data ElasticSearch-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>

创建applicationContext.xml配置文件,引入elasticsearch命名空间 和配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd ">
	<!-- 扫描Dao包,自动创建实例 -->
	<elasticsearch:repositories base-package="com.itheima.dao"/>

	<!-- 扫描Service包,创建Service的实体 -->
	<context:component-scan base-package="com.itheima.service"/>

	<!-- 配置elasticSearch的连接 -->
<!-- cluster-nodes 需要连接的elasticsearch地址 cluster-name 需要连接的集群名称 -->
	<elasticsearch:transport-client id="client" cluster-nodes="localhost:9300" cluster-name="my-elasticsearch"/>

	<!-- 创建Client连接对象 -->
	<bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
		<constructor-arg name="client" ref="client"></constructor-arg>
	</bean>
</beans>

编写实体Article

package com.itheima.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

//@Document 文档对象 (索引信息、文档类型 )
@Document(indexName="blog3",type="article")
public class Article {
    //@Id 文档主键 唯一标识
    @Id
    //@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器 )
    @Field(store=true, index = false,type = FieldType.Integer)
    private Integer id;

    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String title;

    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String content;
    
    @Field(index=true,store=true,type = FieldType.Double)
    private Double price;

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Integer getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Article{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", price=" + price +
                '}';
    }
}

其中,注解解释如下:
@Document(indexName=“blob3”,type=“article”):
indexName:索引的名称(必填项)
type:索引的类型

@Id:主键的唯一标识

@Field(index=true,analyzer=“ik_smart”,store=true,searchAnalyzer=“ik_smart”,type = FieldType.text)
index:是否设置分词
analyzer:存储时使用的分词器
searchAnalyze:搜索时使用的分词器
store:是否存储
type: 数据类型

编写Dao

package com.itheima.dao;

import com.itheima.entity.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {

}

编写Service

接口

package com.itheima.service;

import com.itheima.entity.Article;

public interface ArticleService {
    public void save(Article article);

}

实现类

package com.itheima.service.impl;

import com.itheima.dao.ArticleRepository;
import com.itheima.entity.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public void save(Article article) {
        articleRepository.save(article);
    }

}

创建测试类SpringDataESTest

import com.itheima.entity.Article;
import com.itheima.service.ArticleService;
import org.elasticsearch.client.transport.TransportClient;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)  //测试开始的时候自动创建Spring的应用上下文
//@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
@ContextConfiguration(locations="classpath:applicationContext.xml")//注解来标注我们想要导入某些在容器里的bean。

public class SpringDataESTest {

    @Autowired
    private ArticleService articleService;

    @Resource
    private TransportClient client;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**创建索引和映射*/
    @org.junit.Test
    public void createIndex(){
        elasticsearchTemplate.createIndex(Article.class);
        elasticsearchTemplate.putMapping(Article.class);
    }

    /**添加文档*/
    @org.junit.Test
    public void saveArticle(){
        Article article = new Article();
        article.setId(100);
        article.setTitle("测试SpringData ElasticSearch");
        article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 \n" +
                " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎");
        articleService.save(article);
    }

}

SpringDataElasticSearch的常用操作

使用Spring Data ElasticSearch 增删改查 方法测试

在上面入门案例基础上进行修改

ArticleService

package com.itheima.service;

import com.itheima.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ArticleService {
    //添加
    public void save(Article article);
    //删除
    public void delete(Article article);
    //查询全部
    public Iterable<Article> findAll();
    //分页查询
    public Page<Article> findAll(Pageable pageable);

}

以上方法 都是Spring Data ElasticSearch默认方法

ArticleServiceImpl

package com.itheima.service.impl;

import com.itheima.dao.ArticleRepository;
import com.itheima.entity.Article;
import com.itheima.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public void save(Article article) {
        articleRepository.save(article);
    }

    public void delete(Article article) {
        articleRepository.delete(article);
    }

    public Iterable<Article> findAll() {
        Iterable<Article> iter = articleRepository.findAll();
        return iter;
    }

    public Page<Article> findAll(Pageable pageable) {
        return articleRepository.findAll(pageable);
    }
}

SpringDataESTest

import com.itheima.entity.Article;
import com.itheima.service.ArticleService;
import org.elasticsearch.client.transport.TransportClient;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)  //测试开始的时候自动创建Spring的应用上下文
//@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
@ContextConfiguration(locations="classpath:applicationContext.xml")//注解来标注我们想要导入某些在容器里的bean。

public class SpringDataESTest {

    @Autowired
    private ArticleService articleService;

    @Resource
    private TransportClient client;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**创建索引和映射*/
    @org.junit.Test
    public void createIndex(){
        elasticsearchTemplate.createIndex(Article.class);
        elasticsearchTemplate.putMapping(Article.class);
    }

    /**添加文档*/
    @org.junit.Test
    public void saveArticle(){
        Article article = new Article();
        article.setId(100);
        article.setTitle("测试SpringData ElasticSearch");
        article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 \n" +
                " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎");
        articleService.save(article);
    }

    /**修改文档*/
    @org.junit.Test
    public void update(){
        Article article = new Article();
        article.setId(100);
        article.setTitle("elasticSearch 3.0版本发布...更新");
        article.setContent("ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
        articleService.save(article);
    }

    /**删除文档*/
    @org.junit.Test
    public void delete(){
        Article article = new Article();
        article.setId(100);
        articleService.delete(article);
    }

    /**批量插入*/
    @org.junit.Test
    public void save100(){
        for(int i=1;i<=100;i++){
            Article article = new Article();
            article.setId(i);
            article.setTitle(i+"elasticSearch 3.0版本发布..,更新");
            article.setContent(i+"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
            article.setPrice(i+1.0);
            articleService.save(article);
        }
    }

    
        /**查询全部**/
    @org.junit.Test
    public void findAll(){
        String condition = "版本";

        Iterable<Article> all = articleService.findAll();
        for(Article article: all){
            System.out.println(article);
        }
    }
    
    /**分页查询*/
    @org.junit.Test
    public void findAllPage(){

        //参数1 是页数 参数2是 每页显示多少条 (无须我们自己计算)
        Pageable pageable = PageRequest.of(2,10);
        Page<Article> page = articleService.findAll(pageable);
        for(Article article:page.getContent()){
            System.out.println(article);
        }
    }

}

自定义条件查询

需要添加到 dao层 ArticleRepository接口里才能生效 然后我们在service中调用

自定义匹配规则方法

格式: findBy 固定 Title Content Name Available 这些 都可以换成你自己的字段 但是首字母大写

关键字解释方法
and根据Field1和Field2获得数据findByTitleAndContent(String title,String content);
or根据Field1或Field2获得数据findByTitleOrContent(String title,String content);
is根据Field获得数据findByTitle(String title);
not根据Field获得相反数据findByTitleNot(String title)
between获得指定范围的数据findByPriceBetween(double price1, double price2);
lessThanEqual获得小于等于指定值的数据findByPriceLessThan(double price);
GreaterThanEqual获得大于等于指定值的数据findByPriceGreaterThan(double price);
BeforefindByPriceBefore
AfterfindByPriceAfter
Like比较相识的数据findByNameLike
StartingWith以xx开头的 数据findByNameStartingWith(String Name);
EndingWith以xx结尾的 数据findByNameEndingWith(String Name);
Contains/Containing包含的 数据findByNameContaining(String Name);
In多 值匹配findByNameIn(Collection<String>names)
NotIn多 值 不匹配findByNameNotIn(Collection<String>names)
OrderBy排序 后的数据findByxxxxxOrderByNameDesc(String xxx );

比如: findByTitleAndContent 如果你的表中没有title字段和content那么就无效这个方法

列: List<Article> findByTitleAndContent(String title,String content);

获得指定范围的数据: 方法 findByPriceBetween

列: List<Article> findByPriceBetween(double price1, double price2);

获得小于等于指定值的数据

列: List<Article> findByPriceLessThan(double price);

特别提醒

如果不设置分页信息,上面方法默认带分页,每页显示10条数据。
如果设置分页信息,应该在方法中添加一个参数Pageable

列: Page<Article> findByTitle(String condition, Pageable pageable);

Pageable pageable = PageRequest.of(0, 15); //设置分页 默认是从0页开始。

Page<Article> page = articleService.findByTitle(condition,pageable);//获取数据

排序

findByxxxxxOrderByNameDesc(String Available );

findByxxxxx就是上面的查询字段的条件 比如 findByTitle findByTitleOrContent …

而Name 就是要排序的字段 必须为数值类型 而且不能是id(否则报错)

比如可以是:
@Field(index=true,store=true,type = FieldType.Double)
private Double price;

@Field里 不能加 analyzer=“ik_smart” 和 searchAnalyzer=“ik_smart” 否则报错

Desc 是倒叙 Asc是正序

结合起来就是: findByTitleOrContentOrderByNameDesc

下面会将上面部分方法 演示

更具上面的案例修改代码就行了

dao层接口ArticleRepository

package com.itheima.dao;

import com.itheima.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.Collection;
import java.util.List;

public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {

    //根据title查询
    List<Article> findByTitle(String condition);
    //根据title 查询(含分页)
    Page<Article> findByTitle(String condition, Pageable pageable);
    //根据title and content获得数据
    List<Article> findByTitleAndContent(String title,String content);
    //根据title or content获得数据
    List<Article> findByTitleOrContent(String title,String content);
    //根据title 获取相反条件的数据
    List<Article> findByTitleNot(String title);
    //获取title 里包含的 数据
    List<Article>  findByTitleContaining(String Name);

    //根据title 多 值匹配
    List<Article>  findByTitleIn(Collection<String>names);

    //排序 依据TfindByTitle条件 查询出来的值 然后根据Price字段进行排序
    List<Article>   findByTitleOrderByPriceAsc(String title );
}

service层ArticleService

package com.itheima.service;

import com.itheima.entity.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Collection;
import java.util.List;

public interface ArticleService {
    //保存
    public void save(Article article);
    //删除
    public void delete(Article article);
    //查询全部
    public Iterable<Article> findAll();
    //分页查询
    public Page<Article> findAll(Pageable pageable);

    //根据标题查询
    List<Article> findByTitle(String condition);
    //根据标题查询(含分页)
    Page<Article> findByTitle(String condition, Pageable pageable);
    //根据title and content获得数据
    List<Article> findByTitleAndContent(String title,String content);

    //根据title or content获得数据
    List<Article> findByTitleOrContent(String title,String content);
    //根据title 获取相反条件的数据
    List<Article> findByTitleNot(String title);
    //获取title 里包含的 数据
    List<Article>  findByTitleContaining(String Name);
    //根据title 多 值匹配
    List<Article>  findByTitleIn(Collection<String> names);
    //排序 依据TfindByTitle条件 查询出来的值 然后根据Price字段进行排序
    List<Article>  findByTitleOrderByPriceAsc(String title );

}

service层ArticleService的实现类ArticleServiceImpl

package com.itheima.service.impl;

import com.itheima.dao.ArticleRepository;
import com.itheima.entity.Article;
import com.itheima.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public void save(Article article) {
        articleRepository.save(article);
    }

    public void delete(Article article) {
        articleRepository.delete(article);
    }

    public Iterable<Article> findAll() {
        Iterable<Article> iter = articleRepository.findAll();
        return iter;
    }

    public Page<Article> findAll(Pageable pageable) {
        return articleRepository.findAll(pageable);
    }

    public List<Article> findByTitle(String condition) {
        return articleRepository.findByTitle(condition);
    }
    public Page<Article> findByTitle(String condition, Pageable pageable) {
        return articleRepository.findByTitle(condition,pageable);
    }

    @Override
    public List<Article>  findByTitleAndContent(String title,String content){
        return articleRepository.findByTitleAndContent(title,content);
    }

    @Override
    public List<Article> findByTitleOrContent(String title, String content) {
        return articleRepository.findByTitleOrContent(title,content);
    }

    @Override
    public List<Article> findByTitleNot(String title) {
        return articleRepository.findByTitleNot(title);
    }

    @Override
    public List<Article> findByTitleContaining(String Name) {
        return articleRepository.findByTitleContaining(Name);
    }

    @Override
    public List<Article> findByTitleIn(Collection<String> names) {

        return articleRepository.findByTitleIn(names);
    }

    @Override
    public List<Article> findByTitleOrderByPriceAsc(String title ) {
        return articleRepository.findByTitleOrderByPriceAsc(title );
    }

}

测试

import com.itheima.entity.Article;
import com.itheima.service.ArticleService;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)  //测试开始的时候自动创建Spring的应用上下文
//@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
@ContextConfiguration(locations="classpath:applicationContext.xml")//注解来标注我们想要导入某些在容器里的bean。

public class SpringDataESTest {

    @Autowired
    private ArticleService articleService;

    @Resource
    private TransportClient client;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**创建索引和映射*/
    @org.junit.Test
    public void createIndex(){
        elasticsearchTemplate.createIndex(Article.class);
        elasticsearchTemplate.putMapping(Article.class);
    }

    /**添加文档*/
    @org.junit.Test
    public void saveArticle(){
        Article article = new Article();
        article.setId(100);
        article.setTitle("测试SpringData ElasticSearch");
        article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 \n" +
                " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎");
        articleService.save(article);
    }

    /**修改文档*/
    @org.junit.Test
    public void update(){
        Article article = new Article();
        article.setId(100);
        article.setTitle("elasticSearch 3.0版本发布...更新");
        article.setContent("ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
        articleService.save(article);
    }

    /**删除文档*/
    @org.junit.Test
    public void delete(){
        Article article = new Article();
        article.setId(100);
        articleService.delete(article);
    }

    /**批量插入*/
    @org.junit.Test
    public void save100(){
        for(int i=1;i<=100;i++){
            Article article = new Article();
            article.setId(i);
            article.setTitle(i+"elasticSearch 3.0版本发布..,更新");
            article.setContent(i+"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
            article.setPrice(i+1.0);
            articleService.save(article);
        }
    }

    /**查询全部**/
    @org.junit.Test
    public void findAll(){
        String condition = "版本";

        Iterable<Article> all = articleService.findAll();
        for(Article article: all){
            System.out.println(article);
        }
    }

    /**分页查询*/
    @org.junit.Test
    public void findAllPage(){

        //参数1 是页数 参数2是 每页显示多少条 (无须我们自己计算)
        Pageable pageable = PageRequest.of(2,10);
        Page<Article> page = articleService.findAll(pageable);
        for(Article article:page.getContent()){
            System.out.println(article);
        }
    }

    // ---------------------------------自定义


    /**条件查询*/
    @org.junit.Test
    public void findByTitle(){
        String condition = "版本";
        List<Article> articleList = articleService.findByTitle(condition);
        for(Article article:articleList){
            System.out.println(article);
        }
    }

    /**条件分页查询*/
    @org.junit.Test
    public void findByTitlePage(){
        String condition = "版本";
        Pageable pageable = PageRequest.of(3,10);
        Page<Article> page = articleService.findByTitle(condition,pageable);
        for(Article article:page.getContent()){
            System.out.println(article);
        }
    }

    /**条件查询*/
    //根据Field1和Field2获得数据
    @org.junit.Test
    public void findByTitleAndContent(){
        String title = "版本";
        String content = "搜索服务器";
        List<Article> articleList = articleService.findByTitleAndContent(title,content);
        for(Article article:articleList){
            System.out.println(article);
        }
    }

    /**条件查询*/
    //根据Field1和Field2获得数据
    @org.junit.Test
    public void findByTitleOrContent(){
        String title = "版本";
        String content = "版本";
        List<Article> articleList = articleService.findByTitleOrContent(title,content);
        for(Article article:articleList){
            System.out.println(article);
        }
    }

    /**条件查询*/
    //根据title 获取相反条件的数据
    @org.junit.Test
    public void findByTitleNot(){
        String title = "14elasticSearch 3.0版本发布..,更新";
        List<Article> articleList = articleService.findByTitleNot(title);
        for(Article article:articleList){
            System.out.println(article);
        }
    }
    /**条件查询*/
    //根据title 获取相反条件的数据
    @org.junit.Test
    public void findByTitleContaining(){
        String title = "14";
        List<Article> articleList = articleService.findByTitleContaining(title);
        for(Article article:articleList){
            System.out.println(article);
        }
    }

    /**条件查询*/
    //根据title 多 值匹配
    @org.junit.Test
    public void findByTitleIn(){

        Collection<String> names= new ArrayList<>();
        names.add("版本");
        names.add("14");
        List<Article> articleList = articleService.findByTitleIn(names);
        for(Article article:articleList){
            System.out.println(article);
        }
    }



    /**条件查询*/
    //排序 根据title 来查询出来数据 然后依据Price进行 正序排序
    @org.junit.Test
    public void  findByTitleOrderByPriceAsc(){

        String title = "版本";
        List<Article> articleList = articleService. findByTitleOrderByPriceAsc(title );
        for(Article article:articleList){
            System.out.println(article);
        }
    }

使用Elasticsearch的原生查询对象进行查询

import com.itheima.entity.Article;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)  //测试开始的时候自动创建Spring的应用上下文
//@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
@ContextConfiguration(locations="classpath:applicationContext.xml")//注解来标注我们想要导入某些在容器里的bean。

public class SpringDataESTest {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate; //在applicationContext.xml里配置的
    
    @org.junit.Test
    public void findByNativeQuery() {
        //创建一个SearchQuery对象
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
//-----------------设置查询条件,此处可以使用QueryBuilders termQuery matchQuery 等 创建多种查询----------------
                //queryString查询 条件分词查询 默认or
                .withQuery(QueryBuilders.queryStringQuery("版本").defaultOperator(Operator.OR).defaultField("title"))
                //term 查询 精确分词查询 必须分词列表中有此词汇
// .withQuery(QueryBuilders.termQuery("title", "版本"))
                //match 查询 模糊查询 在匹配前会对搜索词进行分词 然后逐一的 和分词列表进行匹配
// .withQuery(QueryBuilders.matchQuery("title", "版本"))

// ------------ 下面就是 对上面 匹配到的数据 进行 处理---------------------
                //设置分页信息(显示的条数)
                .withPageable(PageRequest.of(0, 50))
                //排序 更具price进行排序 正序
                .withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC))
                //创建SearchQuery对象
                .build();

// --------------将 处理后的数据 打印
        //使用模板对象执行查询
        List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
        for(Article article:articles){
            System.out.println(article);
        }

    }

}

相关文章