ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查

这篇具有很好参考价值的文章主要介绍了ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        本篇是这个系列的最后一篇了,在这之前可以先看看前面的内容:

ES搜索引擎入门+最佳实践(一)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(二)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(三)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(四)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(五)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(六)_flame.liu的博客-CSDN博客

ES搜索引擎入门+最佳实践(七):聚合_flame.liu的博客-CSDN博客

这篇文章将介绍使用ES JAVA API对ES中的数据进行增删改查.

一.添加引用

ES高级客户端已经被放弃,所以这里使用的是elasticsearch-java

        <!--        es java客户端-->
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
        </dependency>
        <!--        jsom与java对象之间的转换-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

 二. 创建ES客户端的配置类

package com.flamelp.productessearch.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ESClientConfig {
//    @Value("${elasticsearch.client.hostname}")
    private String hostname="localhost"; //ES主机地址

//    @Value("${elasticsearch.client.port}")
    private int port=9200; //ES端口号

    /**
     * 创建ES客户端
     * @return ES客户端
     */
    @Bean
    public ElasticsearchClient restHighLevelClient() {
        //创建一个低级客户端,ES JAVA Client API通过低级客户端连接,与ES的版本无关
        RestClient restClient = RestClient.builder(new HttpHost(hostname, port)).build();
        //创建JSON的映射器
        ElasticsearchTransport elasticsearchTransport = new RestClientTransport(restClient,new JacksonJsonpMapper());
        //创建API的客户端
        return new ElasticsearchClient(elasticsearchTransport);
    }
}

三. 在dao层添加对数据增删改查的方法

        索引以及存储对象的格式可以查看前面几篇文章

3.1 编写一个查询需求实体对象

这个对象传递过来的是客户端需要搜索的信息

@Getter
@Setter
@Schema(name = "ProductDetail", description = "")
public class ProductESInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "主键")
    private Integer id;
    @Schema(description = "UID")
    private String uid;
    @Schema(description = "商品名称")
    private String productName;
    @Schema(description = "商品图片")
    private String img;
    @Schema(description = "商品标签")
    private String[] tag;
    @Schema(description = "商品标签字符串形式")
    @JsonIgnore
    private String str_tag;//在导入文档时忽略这个属性
    @Schema(description = "发货地经纬度")
    private LocationPoint location;
    @Schema(description = "发货城市")
    private String city;
    @Schema(description = "原价")
    private BigDecimal originalPrice;
    @Schema(description = "售价")
    private BigDecimal sellPrice;
    @Schema(description = "库存")
    private Integer stockNum;
    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @Schema(description = "更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    @Schema(description = "销量")
    private Integer salesVolume;
    @Schema(description = "推广活动")
    private String promotion;
    @Schema(description = "商品类别")
    private Integer category;
    @Schema(description = "商品评分")
    private BigDecimal score;
    @Schema(description = "好评数量")
    private Integer goodComment;
    @Schema(description = "差评数量")
    private Integer badComment;
    @Schema(description = "店铺编号")
    private Integer shopId;
    @Schema(description = "店铺名称")
    private String shopName;

    /**
     * 将tag转换为数组
     * @return
     */
    public String[] getTag(){
        if(str_tag!=null){
            return StringUtils.split(str_tag,',');
        }else{
            return tag;
        }
    }
}
@Getter
@Setter
@Schema(name = "LocationPoint", description = "发货地点的经纬度")
public class LocationPoint  implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "发货地纬度")
    private double lat;
    @Schema(description = "发货地经度")
    private double lon;
}

3.2 创建 ProductESDao 类

@Component
public class ProductESDao implements IProductESDao {
    @Resource
    ElasticsearchClient esClient;   //ES api 客户端

    private static final String indexName  = "product"; //索引名称
}

接下来在这个类添加需要的方法.

3.3 删除记录

    /**
     * 根据商品编号在ES中删除产品信息
     * @param productId
     * @return ture:成功
     */
    @Override
    public boolean deleteProductESInfo(String productId) throws IOException {
        DeleteResponse response = esClient.delete(builder ->
                builder.index(indexName).id(productId));
        if(response.shards().successful().intValue()>0){
            return true;
        }else{
            return false;
        }
    }

3.4 添加单条记录

/**
     * 根据产品编号在ES中修改产品信息
     * @param productESInfo
     * @return true:成功
     */
    @Override
    public boolean addProductESInfo(ProductESInfo productESInfo) throws IOException {
        IndexResponse response = esClient.index(builder ->
                builder.index(indexName)        //指定索引
                        .id(productESInfo.getId().toString())   //用产品编号作为文档编号
                        .document(productESInfo));              //将对象加入文档
        if(response.version()>0){       //判断文档编号
            return true;
        }else{
            return false;
        }
    }

3.5 修改记录

/**
     * 修改ES中产品信息
     * @param productESInfo
     * @return true:成功
     */
    @Override
    public boolean modifyProductESInfo(ProductESInfo productESInfo) throws IOException {
        //修改文档(覆盖)
        UpdateResponse<ProductESInfo> response = esClient.update(builder ->
                builder.index(indexName)    //指定索引
                        .id(productESInfo.getId().toString())   //指定id
                        .doc(productESInfo),ProductESInfo.class);   //设置需要修改的值
        if(response.shards().successful().intValue()>0){
            return true;
        }else{
            return false;
        }
    }

3.6 批量添加记录

/**
     * 将MySQL中的数据加载到ES索引中
     * * @param list 需要加载到ES中的产品数据
     * @return true表示没有出现错误
     */
    @Override
    public boolean contextLoads(List<ProductESInfo> list) {
        boolean result = true;
        BulkRequest.Builder builder = new BulkRequest.Builder().index(indexName); // 指定索引

        for (ProductESInfo product : list) {
            builder.operations(op -> op.index(in -> in.id(product.getId().toString()).document(product)));
        }
        // 运行批量操作
        try {
            BulkResponse bulk = esClient.bulk(builder.build());
            result = !bulk.errors();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
        return result;
    }

3.7 根据搜索条件查询多条记录

/**
     * 根据搜索条件在ES中搜索产品数据
     * @param qc
     * @return 检索到的产品信息
     */
    @Override
    public List<ProductESInfo> searchProductESInfo(ProductQueryCriteria qc) throws IOException {
        /**
         * 从ES中检索数据一共分四步
         * 1. 创建BoolQuery.Builder(多条件查询构建器)
         * 2. 根据搜索条件往BoolQuery.Builder中添加查询条件
         * 3. 通过es客户端的search发送查询构建器,并设置分页,排序,最终返回搜索响应结果(SearchResponse)
         * 4. 从搜索响应结果(SearchResponse)获得hits并转移到list数据,最后返回结果.
         */
        //创建多条件查询构建起
        BoolQuery.Builder qb = QueryBuilders.bool();
        //添加产品查询条件,并且设置查询权重为2
        qb.must(m->m.match(ma->ma.field("productName").query(qc.getTitle()).boost(2F)));
        //判断商品类型,并将商品类型作为条件添加到查询构建起
        if(qc.getCategory()!=0){
            qb.must(m-> m.term(t->t.field("category").value(qc.getCategory().toString())));
        }
        //判断城市并将城市搜索信息添加到查询构建起
        if(qc.getCity()!=""){
            qb.must(m-> m.term(t->t.field("city").value(qc.getCity())));
        }
        //判断价格范围,约定都为0时,不作为查询条件
        if(qc.getMinPrice()==BigDecimal.valueOf(0)&&qc.getMinPrice()==BigDecimal.valueOf(0)){
            qb.must(m->m.range(r->r.field("sellPrice")
                    .gte(JsonData.of(qc.getMinPrice()))
                    .lte(JsonData.of(qc.getMaxPrice()))));
        }
        //判断是否需要根据标签查询,这里指定至少需要匹配一个标签
        if(qc.getTag()!=null){
            qb.should(s->s.termsSet(ts->ts.field("tag")
                    .terms(qc.getTag())
                    .minimumShouldMatchScript(ss->ss.inline(il->il.source("1")))
                    .boost(1.1F)));
        }
        //查询店铺名字中是否包含有商品名称
        if(qc.getTitle()!=""){
            qb.should(s-> s.match(ma->ma.field("shopName").query(qc.getTitle()).boost(1.1F)));
        }
        //按照地理位置进行查询,50km范围内的商品发货地
        if(qc.getPoint()!=null){
            qb.should(s->s.geoDistance(g->g.field("location")
                    .location(loc->loc.latlon(lat->lat.lat(qc.getPoint().getLat()).lon(qc.getPoint().getLon())))
                    .distance("50km").boost(1.2F)));
        }
        //向ES客户端发送搜索命令,并返回搜索响应(SearchResponse)
        SearchResponse<ProductESInfo> response= esClient.search(builder -> builder
                        .query(q->q.bool(b->qb))    //设置查询
                        .from(qc.getFrom())     //分页:记录开始的序号
                        .size(qc.getSize())     //分页:每页显示的数据量
                        .sort(s->s.field(f->f.field(qc.getOrderByCode().toString()).order(SortOrder.Desc)))    //按照相关度降序排列
                ,ProductESInfo.class);//SortOrder.Desc
        //从搜索响应SearchResponse中获得查询的数据结果
        List<Hit<ProductESInfo>> hits = response.hits().hits();
        List<ProductESInfo> productESInfos = new ArrayList<>();
        for(Hit<ProductESInfo> hit: hits){
            ProductESInfo productESInfo = hit.source();
            productESInfos.add(productESInfo);
        }
        return productESInfos;
    }

上面这个方法是ES操作的核心, 毕竟ES就是为了检索数据而出现的.上面代码的注释比较全,只对部分内容做些解释.

1. BoolQuery.Builder 是创建一个多条件查询构造器,我们可以在这个构造器里面添加查询的方法,最终发送给ES的时候将转换为JSON代码;

2. 多条件查询时需要判断是否需要添加条件;

3.must表示这个查询条件是必须的,这里有多个must拼接起来,在最终会拼接位一个must的jsom语句,should也是一样.

4. match表示分词查询,term表示完全匹配,range用户范围查询,需要指定最大值和最小值,geoDistance是进行地理位置查询.

5. 这里有意思的是terms,在es中可以用来匹配一个数组里面的值,但是在这个api中terms好像不是这样的,所以这里引用了termsSet这个操作,可以起到相同的作用,需要注意的是,这个操作需要指定minimumShouldMatchScript或者minimumShouldMatchField.

        minimumShouldMatchScript:指定一个脚本告诉ES,在匹配集合数据时需要匹配几条,后面 il->il.source("1") 表示脚本返回数据为1,只需要匹配一条.

        minimumShouldMatchField:指定索引中的一个字段,这个字段必须返回一个数字,然后用这个数字规定需要在集合里面匹配的记录数.(不知道为什么有个这么奇怪的规则).

6.boots这里是设置每一项查询的得分权重.

好了,就到这里了.有问题就留言吧,看到就回.文章来源地址https://www.toymoban.com/news/detail-652598.html

到了这里,关于ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【项目实战】基于高并发服务器的搜索引擎

    作者:爱写代码的刚子 时间:2024.4.24 前言:基于高并发服务器的搜索引擎,引用了第三方库cpp-httplib,cppjieba,项目的要点在代码注释中了 index.html index.hpp log.hpp parser.cc(用于对网页的html文件切分且存储索引关系) searcher.hpp util.hpp http_server.cc(用于启动服务器和搜索引擎)

    2024年04月28日
    浏览(34)
  • 项目1在线交流平台-6.Elasticsearch分布式搜索引擎-3.ES结合Kafka应用-开发社区搜索功能

    参考牛客网高级项目教程 狂神说Elasticsearch教程笔记 尚硅谷Elasticsearch教程笔记 1.在业务层处理好搜索帖子的服务 包括保存帖子到ES服务器 从服务器中删除帖子 从服务器中查询帖子 2.发布事件 在controller层,结合kafka,发布帖子、增加评论时,数据放入消息队列 异步消费消息

    2024年02月02日
    浏览(36)
  • 【搜索引擎Solr】配置 Solr 以获得最佳性能

    Apache Solr 是广泛使用的搜索引擎。有几个著名的平台使用 Solr;Netflix 和 Instagram 是其中的一些名称。我们在 tajawal 的应用程序中一直使用 Solr 和 ElasticSearch。在这篇文章中,我将为您提供一些关于如何编写优化的 Schema 文件的技巧。我们不会讨论 Solr 的基础知识,我希望您了解

    2024年02月16日
    浏览(27)
  • 详解最热门搜索引擎——ES

    ​ 互联网发展早期的时候,对于一般的公司储存的数据量不是那么的大,所以很多公司更倾向于使用数据库去存储和查询数据,如:现在去MySQL中查询数据,大概的查询方式就是:select * from table where filed like “%XXX%”或者其他方式,但是,如果我们在查询的时候没有用到或命

    2023年04月10日
    浏览(30)
  • 分布式搜索引擎ES

    elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 ELK技术栈 elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应

    2024年02月04日
    浏览(26)
  • 【分布式搜索引擎es】

    elasticsearch最擅长的是 搜索 和 数据分析 。 查询文档 常见的查询类型包括: 查询所有 :查询出所有数据,一般测试用。例如:match_all 全文检索(full text)查询 :利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如: match_query multi_match_query 精确查询 :根据精确

    2024年02月10日
    浏览(35)
  • RediSearch比Es搜索还快的搜索引擎

    RediSearch是一个Redis模块,为Redis提供查询、二次索引和全文搜索。要使用RediSearch,首先要在Redis数据上声明索引。然后可以使用重新搜索查询语言来查询该数据。RedSearch使用压缩的反向索引进行快速索引,占用内存少。RedSearch索引通过提供精确的短语匹配、模糊搜索和数字过

    2024年04月11日
    浏览(26)
  • 搜索引擎ElasticSearch分布式搜索和分析引擎学习,SpringBoot整合ES个人心得

    Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,

    2024年02月04日
    浏览(53)
  • Elasticsearch (ES) 搜索引擎: 搜索功能:搜索分页、搜索匹配、全文搜索、搜索建议、字段排序

    原文链接:https://xiets.blog.csdn.net/article/details/132348920 版权声明:原创文章禁止转载 专栏目录:Elasticsearch 专栏(总目录) ES 搜索 API 官网文档:Search APIs 先创建一个索引,并写入一些文档用于搜索示例: 写入一些文档示例: 官网API:The _source option 搜索结果中的文档数据封装

    2024年02月08日
    浏览(43)
  • 搜索引擎ES-RestHighLevelClient

    前言:本篇文章,主要讲述如何引入RestHighLevelClient,以及对其API的调用,属于入门级别的接口实用。适用于由于工作需要及时了解的童靴们以及初学者。想要了解ES底层更多内容的童鞋们,本篇文章并不适合 ! 前言:对比mysql,了解ES 首先通过图片对比我们了解的关系型数据

    2024年02月08日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包