当前位置: 代码网 > it编程>编程语言>Java > Spring Data Elasticsearch使用方式(Elasticsearch)

Spring Data Elasticsearch使用方式(Elasticsearch)

2025年04月17日 Java 我要评论
1. 项目部署1.1 添加依赖在项目的 pom.xml 中引⼊spring data elasticsearch的启动器。<dependency> <groupid>org.s

1. 项目部署

1.1 添加依赖

在项目的 pom.xml 中引⼊spring data elasticsearch的启动器。

<dependency>
 <groupid>org.springframework.boot</groupid>
 <artifactid>spring-boot-starter-data-elasticsearch</artifactid>
</dependency>

1.2 配置application.yml 文件

spring:
 data:
   elasticsearch:
     cluster-name: csdn-elastic
     cluster-nodes: 127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303

需要注意的是,spring data elasticsearch底层使⽤的不是elasticsearch提供的resthighlevelclient,⽽是 transportclient,并不采⽤http协议通信,⽽是访问elasticsearch对外开放的tcp端⼝。

我们在之前集群配置 中,设置的端⼝分别是:9301、9302、9303。

1.3 测试是否注入成功

在test测试⽂件夹下的com.csdn.es包下创建⼀个springdataestests测试类。通过@autowired注解对 elasticsearchtemplate进⾏注⼊,测试对象是否可以获取到。

package com.csdn.es;
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.data.elasticsearch.core.elasticsearchtemplate;
import org.springframework.test.context.junit4.springrunner;
@runwith(springrunner.class)
@springboottest
public class springdataestests {
 @autowired
 private elasticsearchtemplate template;
 @test
 public void check() {
 system.err.println(template);
 }
}

注: 使用 spring data elasticsearch 是springboot 版本不能太高,建议使用 2.1.6.release 版本。如果有 rest client 版本太高也会注入失败,建议使用 6.4.3 。

2. 操作

2.1 索引库操作

2.1.1 实体类注解

1.我们在product实体类上添加下⾯的⼀些注解。

package com.csdn.pojo;
import lombok.allargsconstructor;
import lombok.data;
import lombok.noargsconstructor;
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;
@data
@noargsconstructor
@allargsconstructor
@document(indexname = "csdn", type = "product", shards = 3, replicas = 1)
public class product {
 @id
 private long id;
 @field(type = fieldtype.text, analyzer = "ik_max_word")
 private string title; // 标题
 @field(type = fieldtype.keyword)
 private string category; // 分类
 @field(type = fieldtype.keyword)
 private string brand; // 品牌
 @field(type = fieldtype.double)
 private double price; // 价格
 @field(type = fieldtype.keyword, index = false)
 private string images; // 图⽚地址
}

2.在springdataestests类中定义创建索引的createindex()⽅法。

@test
public void createindex() {
 // 创建索引库,并制定实体类的字节码
 template.createindex(product.class);
}

2.1.2 创建映射

刚才的注解已经把映射关系也配置上了,所以创建映射只需要这样:

@test
public void createmapping() {
 template.putmapping(product.class);
}

2.2 索引数据crud操作

sde的索引数据crud操作并没有封装在elasticsearchtemplate类中,⽽是有⼀个叫做elasticsearchrepository的 接⼝中。

在com.csdn.respository包下⾃定义productrepository接⼝,并继承elasticsearchrespository接⼝。

package com.csdn.respository;
import com.yx.pojo.product;
import org.springframework.data.elasticsearch.repository.elasticsearchrepository;
public interface productrepository extends elasticsearchrepository<product, long> {
 
}

2.2.1 创建索引数据

1.先来看单个创建。在springdataestests类中定义adddocument()⽅法。

@autowired
private productrepository productrepository;
@test
public void adddocument() {
 product product = new product(1l, "⼩⽶⼿机mix", "⼿机", "⼩⽶", 2899.00,
"http://image.yx.com/12479122.jpg");
 // 添加索引数据
 productrepository.save(product);
}

2.再来看批量创建。在springdataestests类中定义adddocuments()⽅法。

@test
public void adddocuments() {
 // 准备⽂档数据
 list<product> list = new arraylist<>();
 list.add(new product(2l, "坚果⼿机r1", "⼿机", "锤⼦", 3699.00,
"http://image.yx.com/12479122.jpg"));
 list.add(new product(3l, "华为meta20", "⼿机", "华为", 4499.00,
"http://image.yx.com/12479122.jpg"));
 list.add(new product(4l, "⼩⽶pro", "⼿机", "⼩⽶", 4299.00,
"http://image.yx.com/12479122.jpg"));
 list.add(new product(5l, "荣耀v20", "⼿机", "华为", 2799.00,
"http://image.yx.com/12479122.jpg"));
 // 添加索引数据
 productrepository.saveall(list);
}

2.2.2 查询索引数据

1.根据id查询数据

@test
public void findbyid() {
 optional<product> optional = productrepository.findbyid(1l);
 product defaultproduct = new product();
 defaultproduct.settitle("默认商品数据");
 // orelse(t other)⽅法:如果optional对象中封装的泛型为null,则将orelse()⽅法的参数作为返回值
 product product = optional.orelse(defaultproduct);
 system.err.println(product);
}

2.查询所有数据

@test
public void findall() {
 iterable<product> list = productrepository.findall();
 list.foreach(system.err::println);
}

2.2.3 ⾃定义⽅法查询

在productrepository接⼝中定义根据商品的价格区间查询商品数据的findbypricebetween()⽅法。

/**
* 根据商品的价格区间查询商品数据
* @param from 开始价格
* @param to 结束价格
* @return 符合条件的商品数据
*/
list<product> findbypricebetween(double from, double to);

⽆需写实现,sde会⾃动帮我们实现该⽅法,我们只需要⽤即可。在springdataestests类中定义 findbypricebetween()⽅法。

@test
public void findbypricebetween() {
 list<product> products = productrepository.findbypricebetween(3000d, 5000d);
 products.foreach(system.err::println);
}

2.3 原⽣查询案例

在com.csdn.mapper包下⾃定义搜索结果映射productsearchresultmapper类。

package com.csdn.esclient;

import com.google.gson.gson;
import org.elasticsearch.action.search.searchresponse;
import org.elasticsearch.search.searchhit;
import org.elasticsearch.search.searchhits;
import org.elasticsearch.common.text.text;
import org.elasticsearch.search.fetch.subphase.highlight.highlightfield;
import org.springframework.data.domain.pageable;
import org.springframework.data.elasticsearch.core.searchresultmapper;
import org.springframework.data.elasticsearch.core.aggregation.aggregatedpage;
import org.springframework.data.elasticsearch.core.aggregation.impl.aggregatedpageimpl;

import java.util.arraylist;
import java.util.list;
import java.util.map;

/**
 * 1.接口 searchresultmapper 表示用来自定义查询结果映射,将结果按照开发者的配置,进行重组,然后返回客户端
 * 2.重写 mapresults
 */
/** ⾃定义查询结果映射,⽤于处理⾼亮显示 */
public class productsearchresulmapper implements searchresultmapper {
    @override
    public <t> aggregatedpage<t> mapresults(searchresponse searchresponse, class<t> aclass, pageable pageable) {
        // 记录总条数
        long totalhits = searchresponse.gethits().gettotalhits();
        // 记录列表(泛型) - 构建aggregate使⽤
        list<t> list = new arraylist<>();
        // 获取搜索结果(真正的的记录)
        searchhits hits = searchresponse.gethits();
        gson gson = new gson();
        for (searchhit hit : hits) {
            if (hits.gethits().length <= 0) {
                return null;
            }
            // 将原本的json对象转换成map对象
            map<string, object> map = hit.getsourceasmap();
            // 获取⾼亮的字段map
            map<string, highlightfield> highlightfields = hit.gethighlightfields();
            for (map.entry<string, highlightfield> highlightfield : highlightfields.entryset()) {
                // 获取⾼亮的key
                string key = highlightfield.getkey();
                // 获取⾼亮的value
                highlightfield value = highlightfield.getvalue();
                // 实际fragments[0]就是⾼亮的结果,⽆需遍历拼接
                text[] fragments = value.getfragments();
                // 因为⾼亮的字段必然存在于map中,就是key值
                map.put(key, fragments[0].tostring());
            }
            // 把map转换成对象
            t item = gson.fromjson(gson.tojson(map), aclass);
            list.add(item);
        }
        // 返回的是带分⻚的结果
        return new aggregatedpageimpl<>(list, pageable, totalhits);
    }
}

java测试类:

package com.csdn.es;

import com.qf.esclient.productsearchresulmapper;
import com.qf.pojo.product;
import org.elasticsearch.index.query.querybuilders;
import org.elasticsearch.search.aggregations.aggregationbuilders;
import org.elasticsearch.search.fetch.subphase.highlight.highlightbuilder;
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.data.domain.pagerequest;
import org.springframework.data.domain.sort;
import org.springframework.data.elasticsearch.core.elasticsearchtemplate;
import org.springframework.data.elasticsearch.core.aggregation.aggregatedpage;
import org.springframework.data.elasticsearch.core.query.fetchsourcefilter;
import org.springframework.data.elasticsearch.core.query.nativesearchquerybuilder;
import org.springframework.test.context.junit4.springrunner;

import java.util.list;

@springboottest
@runwith(springrunner.class)
public class springdataestests {

    @autowired
    private elasticsearchtemplate template;

    @test
    public void test01() {
        // 1.创建原生查询语句构建
        nativesearchquerybuilder builder = new nativesearchquerybuilder();
        // 2.通过nativesearchquerybuilder指定过滤器条件
        builder.withsourcefilter(new fetchsourcefilter(null,null));
        // 3.添加词条搜索条件
        builder.withquery(querybuilders.matchquery("title","手机"));
        // 4.分页操作:当前页其实位置的下标
        builder.withpageable(pagerequest.of(0, 2, sort.by(sort.direction.asc,
                "price")));
        // 5.高亮显示 todo
        highlightbuilder.field field = new highlightbuilder.field("title");
        field.pretags("<span style='color:red'>");
        field.posttags("</span>");
        builder.withhighlightfields(field);

        // 6.聚合:分组。参数解析:terms()方法指定分组的名称(聚合名称)
        builder.addaggregation(aggregationbuilders.terms("brandagg").field("brand"));
        // 7.构建查询的条件,并且执行查询
        aggregatedpage<product> packages = template.queryforpage(builder.build(), product.class,new productsearchresulmapper());


        long total = packages.gettotalelements();
        int totalpages = packages.gettotalpages();
        list<product> list = packages.getcontent();
        system.out.println("总条数:" + total);
        system.out.println("总⻚数:" + totalpages);
        system.out.println("数据:");
        list.foreach(system.out::println);


        // 聚合
        /**
        aggregations aggregations = packages.getaggregations();
        // 导包org.elasticsearch.search.aggregations.bucket.terms.terms
        terms terms = aggregations.get("brandagg");
        terms.getbuckets().foreach(b -> {
            system.err.println("品牌:" + b.getkeyasstring());
            system.err.println("count:" + b.getdoccount());
        });
         */
    }

}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com