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客户端*/@Beanpublic 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 = "商品标签字符串形式")@JsonIgnoreprivate 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 {@ResourceElasticsearchClient esClient; //ES api 客户端private static final String indexName = "product"; //索引名称
}
接下来在这个类添加需要的方法.
3.3 删除记录
/*** 根据商品编号在ES中删除产品信息* @param productId* @return ture:成功*/@Overridepublic 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:成功*/@Overridepublic 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:成功*/@Overridepublic 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表示没有出现错误*/@Overridepublic 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 检索到的产品信息*/@Overridepublic 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();//添加产品查询条件,并且设置查询权重为2qb.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这里是设置每一项查询的得分权重.
好了,就到这里了.有问题就留言吧,看到就回.
相关文章:
ES搜索引擎入门+最佳实践(九):项目实战(二)--elasticsearch java api 进行数据增删改查
本篇是这个系列的最后一篇了,在这之前可以先看看前面的内容: ES搜索引擎入门最佳实践(一)_flame.liu的博客-CSDN博客 ES搜索引擎入门最佳实践(二)_flame.liu的博客-CSDN博客 ES搜索引擎入门最佳实践(三)_flame.liu的博客-CSDN博客 ES搜索引擎入门最佳实践(四)_flame.liu的博…...
android内存分析工具记录,请利用好最后2个神器
相机见证了java内存暴增和native持续增长的问题,因此这里记录一下使用的工具情况,方便后续继续使用 一、java 内存 如果是java层的内存可以直接借助leakCanary工具,配置也很简单,直接在build.gradle中添加依赖即可: …...
安科瑞变电所运维平台在电力系统中应用分析
摘要:现代居民生活、工作对电力资源的需求量相对较多,给我国的电力产业带来了良好的发展机遇与挑战。探索电力系统基本构成, 将变电运维安全管理以及相应的设备维护工作系统性开展,能够根据项目实践工作要求,将满足要求…...
uniapp开发微信小程序使用painter将页面转换为图片并保存到本地相册
引言 我使用到painter的原因是,在uniapp开发微信小程序时,需要将一个页面的内容转换成图片保存到本地相册。 起初在网上找到很多都是在uniapp中使用 html2canvas 将网页转换成图片再jspdf将图片转换为pdf,但是这种方式在小程序环境不支持&am…...
790. 数的三次方根
文章目录 QuestionIdeasCode Question 给定一个浮点数 n ,求它的三次方根。 输入格式 共一行,包含一个浮点数 n 。 输出格式 共一行,包含一个浮点数,表示问题的解。 注意,结果保留 6 位小数。 数据范围 −10000≤…...
POSTGRESQL 关于2023-08-14 数据库自动启动文章中使用KILL 来进行配置RELOAD的问题解释...
开头还是介绍一下群,如果感兴趣Polardb ,mongodb ,MySQL ,Postgresql ,redis ,SQL SERVER ,ORACLE,Oceanbase 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请加 liuaustin3微信号 &…...
vue 使用插件高德地图--vue-amap
第一步:安装 vue-amap npm install vue-amap第二步:在你的 Vue 项目中注册 vue-amap: // main.js import Vue from vue; import VueAMap from vue-amap;Vue.use(VueAMap);VueAMap.initAMapApiLoader({// 高德开发者平台申请key值key: cc9c098…...
减速比如何计算
减速比是用来衡量机械系统中输入轴和输出轴转速之间的比例关系,通常用来描述传动装置(如齿轮传动、皮带传动等)的效果。计算减速比的公式取决于传动装置的类型。以下是一些常见传动装置的减速比计算方法: 齿轮传动: 对…...
HarmonyOS/OpenHarmony应用开发-ArkTSAPI组件总体分类与说明(下)
六、文本与输入 Text 显示一段文本的组件。 Span 作为Text组件的子组件,用于显示行内文本片段的组件。 Search 搜索框组件,适用于浏览器的搜索内容输入框等应用场景。 TextArea 多行文本输入框组件,当输入的文本内容超过组件宽度时会自动换行…...
势函数和鞅的停时定理
前置芝士 鞅: 鞅是一类特殊的随机过程,假设我们从一开始就在观察一场赌博游戏,现在已经得到了前t秒的观测值,那么当第t1 秒观测值的期望等于第t秒的观测值时,我们称这是一个公平赌博游戏。 具体来说,对于…...
途乐证券-炒股开户流程是怎样的?
炒股是一种危险较大但收益也相对较高的出资方法,而开户则是出资炒股的前提。跟着科技的开展,炒股开户已经能够在线完结,但流程相对来说仍是比较繁琐的。那么,炒股开户流程是怎样的呢?下面从多个视点剖析。 一、炒股开户…...
Eclipse如何设置快捷键
在eclopse设置注释行和取消注释行 // 打开eclipse,依次打开:Window -> Preferences -> General -> Key,...
刷享全球美好 中信银行信用卡推出跨境消费系列活动
来源 | 镭射财经(leishecaijing) 日前,文旅部办公厅发布通知,恢复全国旅行社及在线旅游企业经营中国公民赴有关国家和地区(第三批)出境团队旅游和“机票酒店”业务,出境跟团游国家和地区由此前…...
LeetCode算法心得——限制条件下元素之间的最小绝对差(TreeSet)
大家好,我是晴天学长,今天用到了Java一个非常实用的类TreeSet,能解决一些看起来棘手的问题。 1 )限制条件下元素之间的最小绝对差 2) .算法思路 初始化变量:n为列表nums的大小。 min为整型最大值,用于记录…...
MySQL表的基础操作(crud)
1. 新增(Create) insert into 表名 values (值, 值…); 此处列出的这些值,的数目和类型要和表的列相匹配。 -- 在student 表中插入学号1,姓名zhangsan的数据 insert into student values(1, zhangsan); -- 指定列插入 insert into student …...
vue中的activated和deactivated
目录 一、简介二、使用 一、简介 当页面被keep-alive缓存下来的时候,vue提供两个钩子函数 activated被 keep-alive 缓存的组件激活时调用。deactivated被 keep-alive 缓存的组件失活时调用。 当keepalive页面缓存,有activated钩子和created钩子函数时 …...
unity 发布报错 The type or namespace name `UnityEditor‘ could not be found.
引用了UnityEditor的内容,发布当然会报错啦 加上宏判断就好啦...
在ubuntu中将dict.txt导入到数据库sqlite3
将dict.txt导入到数据库 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//创建泵打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…...
nginx 代理postgresql
首先,Nginx为我们的数据库增加了额外的安全层。Nginx提供了一整套的选项,这使得管理访问和保护数据库变得很容易。例如,我们可以配置为只有一小部分IP地址可以访问数据库。 PostgreSQL不使用HTTP或HTTPS,而是使用一个新块儿strea…...
小程序 CSS-in-JS 和原子化的另一种选择
小程序 CSS-in-JS 和原子化的另一种选择 小程序 CSS-in-JS 和原子化的另一种选择 介绍快速开始 pandacss 安装和配置 0. 安装和初始化 pandacss1. 配置 postcss2. 检查你的 panda.config.ts3. 修改 package.json 脚本4. 全局 css 注册 pandacss5. 配置的优化与别名 weapp-pand…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
