当前位置: 首页 > news >正文

SpringData ElasticSearch - 简化开发,完美适配 Spring 生态

目录

一、SpringData ElasticSearch

1.1、环境配置

1.2、创建实体类

1.3、ElasticsearchRestTemplate 的使用

1.3.1、创建索引 设置映射

1.3.2、创建索引映射注意事项(必看)

1.3.3、简单的增删改查

1.3.4、搜索

1.4、ElasticsearchRepository

1.4.1、使用方式

1.4.2、简单的增删改查

1.4.3、分页排序查询


一、SpringData ElasticSearch


1.1、环境配置

a)依赖如下:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>

b)配置文件如下:

spring:elasticsearch:uris: env-base:9200

1.2、创建实体类

a)简单结构如下(后续实例,围绕此结构展开):

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/***  @shards: 主分片数量*  @replicas: 副本分片数量*/
@Document(indexName = "album_info", shards = 1, replicas = 0)
data class AlbumInfoDo(/*** @Id: 表示文档中的主键,并且会在保存在 ElasticSearch 数据结构中 {"id": "", "userId": "", "title": ""}*/@Id@Field(type = FieldType.Keyword)val id: Long? = null,/*** @Field: 描述 Java 类型中的属性映射*      - name: 对应 ES 索引中的字段名. 默认和属性同名*      - type: 对应字段类型,默认是 FieldType.Auto (会根据我们数据类型自动进行定义),但是建议主动定义,避免导致错误映射*      - index: 是否创建索引. text 类型创建倒排索引,其他类型创建正排索引.  默认是 true*      - analyzer: 分词器名称.  中文我们一般都使用 ik 分词器(ik分词器有 ik_smart 和 ik_max_word)*/@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")val title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")val content: String,
)

b)复杂嵌套结构如下:

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(indexName = "album_list")
data class AlbumListDo(@Id@Field(type = FieldType.Keyword)var id: Long,@Field(type = FieldType.Nested) // 表示一个嵌套结构var userinfo: UserInfoSimp,@Field(type = FieldType.Text, analyzer = "ik_max_word")var title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")var content: String,@Field(type = FieldType.Nested) // 表示一个嵌套结构var photos: List<AlbumPhotoSimp>,
)data class UserInfoSimp(@Field(type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")val username: String,@Field(type = FieldType.Keyword, index = false)val avatar: String,
)data class AlbumPhotoSimp(@Field(type = FieldType.Integer, index = false)val sort: Int,@Field(type = FieldType.Keyword, index = false)val photo: String,
)

对于一个小型系统来说,一般也不会创建这种复杂程度的文档,因为会涉及到很多一致性问题, 需要通过大量的 mq 进行同步,给系统带来一定的开销. 

因此,一般会将需要进行模糊查询的字段存 Document 中(es 就擅长这个),而其他数据则可以在 Document 中以 id 的形式进行存储.   这样就既可以借助 es 高效的模糊查询能力,也能减少为保证一致性而带来的系统开销.  从 es 中查到数据后,再通过其他表的 id 从数据库中拿数据即可(这点开销,相对于从大量数据的数据库中进行 like 查询,几乎可以忽略).

1.3、ElasticsearchRestTemplate 的使用

1.3.1、创建索引 设置映射

@SpringBootTest(classes = [DataEsApplication::class])
class DataEsApplicationTests {@Resource private lateinit var elasticsearchTemplate: ElasticsearchRestTemplate@Testfun test1() {//创建索引elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).create()//设置映射elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).putMapping(elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).createMapping())}}

效果如下:

1.3.2、创建索引映射注意事项(必看)

a)在没有创建索引库和映射的情况下,也可以直接向 es 库中插入数据,如下代码:

    @Testfun test1() {val o = AlbumListDo(id = 1,userinfo = UserInfoSimp(userId = 1,username = "cyk",avatar = "http:photo1.com"),title = "天气很好的一天",content = "早上起来,我要好好学习,然去公园散步~",photos = listOf(AlbumPhotoSimp(1, "www.photo1"),AlbumPhotoSimp(2, "www.photo2")))val result = esTemplate.save(o)println(result)}

b)即使上述代码中 AlbumListDo 中有各种注解标记,但是不会生效!!! es 会根据插入的数据,自动转化数据结构(无视你的注解).

c)因此,一定要先创建索引库和映射,再进行数据插入!

1.3.3、简单的增删改查

    /*** 更新和添加都是这样* 更新的时候会根据 id 进行覆盖*/@Testfun testSave() {//保存单条数据val a1 = AlbumInfoDo(id = 1,userId = 10000,title = "今天天气真好",content = "学习完之后,我要出去好好玩")val result = elasticsearchTemplate.save(a1)println(result)//保存多条数据val list = listOf(AlbumInfoDo(2, 10000, "西安六号线避雷", "前俯后仰。他就一直在那前后动。他背后是我朋友,我让他不要挤了,他直接就急了,开始故意很大力的挤来挤去。"),AlbumInfoDo(3, 10000, "字节跳动快上车~", "#内推 #字节跳动内推 #互联网"),AlbumInfoDo(4, 10000, "连王思聪也变得低调老实了", "如今的王思聪,不仅交女友的质量下降,在网上也不再像以前那样随意喷这喷那。显然,资金的紧张让他低调了许多"))val resultList = elasticsearchTemplate.save(list)resultList.forEach(::println)}@Testfun testDelete() {//根据主键删除elasticsearchTemplate.delete("1", AlbumInfoDo::class.java)}@Testfun testGet() {val result = elasticsearchTemplate.get("1", AlbumInfoDo::class.java)println(result)}

补充一个修改:

    override fun update(msg: UpdateAlbumInfoMsg): Int {val query = UpdateQuery.builder(msg.albumId.toString()) //指定修改的文档 id.withDocument(org.springframework.data.elasticsearch.core.document.Document.create() //指定修改字段.append("title", msg.title) .append("content", msg.content).append("ut_time", msg.utTime)).build()val result = restTemplate.update(query, IndexCoordinates.of("album_doc")).resultreturn result.ordinal}

1.3.4、搜索

a)一般搜索

import org.cyk.dataes.model.AlbumInfoDo
import org.elasticsearch.index.query.QueryBuilders
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder
import org.junit.jupiter.api.Test
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.ElasticsearchRestTemplate
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder
import javax.annotation.Resource@SpringBootTest(classes = [DataEsApplication::class])
class TemplateTests {@Resource private lateinit var elasticsearchTemplate: ElasticsearchRestTemplate/*** 全文检索查询(match_all)*/@Testfun testMatchAllQuery() {val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)println("总数为: ${hits.totalHits}")hits.forEach { println(it.content) }}/*** 全文检索查询(match)*/@Testfun testMatchQuery() {val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "天气")).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 精确查询(term)*/@Testfun testTerm() {val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.termQuery("user_id", 10001)).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 范围查询*/@Testfun testRangeQuery() {val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.rangeQuery("id").gte(1).lt(4)).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 复合查询(bool)*/@Testfun testBoolQuery() {val boolQuery = QueryBuilders.boolQuery()//必要条件: query.must 得到一个集合val mustList = boolQuery.must()mustList.add(QueryBuilders.rangeQuery("user_id").gte(10000).lt(10003))//其他的搜索条件集合的获取方式类似val mustNotList = boolQuery.mustNot()val should = boolQuery.should()//当然,还有一种简化的写法,如下,下述代码相当于 query.should().add(QueryBuilders.matchAllQuery())boolQuery.should(QueryBuilders.matchAllQuery())val query =  NativeSearchQueryBuilder().withQuery(boolQuery).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 排序和分页*/@Testfun testSortAndPage() {val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).withPageable(PageRequest.of(0, 3) //参数一: 页码(从 0 开始),size 每页查询多少条数据.withSort(Sort.by(Sort.Order.desc("id"))) //根据 id 降序排序(这里也可以根据多个字段进行升序降序)).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach{ println(it.content) }}/*** 高亮搜索*/@Testfun testHighLight() {//定义高亮字段val field = HighlightBuilder.Field("title")//a) 前缀标签field.preTags("<span style='color:red'>")//b) 后缀标签field.postTags("</span>")//c) 高亮的片段长度(多少个几个字需要高亮,一般会设置的大一些,让匹配到的字段尽量都高亮)field.fragmentSize(10)//d) 高亮片段的数量field.numOfFragments(1)// withHighlightFields(Field... 高亮字段数组)val query = NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "天气")).withHighlightFields(field).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)//注意,hit.content 中本身是没有高亮数据的,因此这里需要手工处理hits.forEach {val result = it.content//根据高亮字段名称,获取高亮数据集合,结果是 List<String>val hList = it.getHighlightField("title")if(hList.size > 0) {//有高亮数据result.title = hList.get(0)}println(result)}}}

b)基于 completionSuggestion 实现自动补全

data 如下:

@Document(indexName = "album_doc")
data class AlbumDocDo (@Id@Field(type = FieldType.Keyword)val id: Long,@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word", copyTo = ["suggestion"])val title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")val content: String,@Field(name = "ct_time", type = FieldType.Long)val ctTime: Long,@Field(name = "ut_time", type = FieldType.Long)val utTime: Long,@CompletionField(maxInputLength = 100, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")val suggestion: Completion? = null,
)

自动补全的字段必须是 completion 类型.  自动补全字段为 title,将他 copy 到了 suggestion 字段,实现自动补全. 

    override fun suggestTexts(o: AlbumSuggestDto): List<String> {val suggest = SuggestBuilder().addSuggestion("title_suggest",     //自定义补全名SuggestBuilders.completionSuggestion("suggestion") //自动补全时需要查询的字段.prefix(o.text)        //要进行补全的值(用户搜索框中输入的).skipDuplicates(true)  //如果查询时有重复的词条,是否自动跳过(true 为跳过).size(o.limit)         //获取多少个结果)val query = NativeSearchQueryBuilder().withSuggestBuilder(suggest).build()val hits = restTemplate.search(query, AlbumDocDo::class.java)val suggests = hits.suggest?.getSuggestion("title_suggest") //根据自定义补全名获取对应的补全结果集?.entries?.get(0)      //结果集(记录了根据什么前缀(prefix)进行自动补全,补全的结果对象...)?.options?.map(::map) ?: emptyList()  //补全的结果对象(其中 text 就是自动补全的结果)return suggests}private fun map(hit: Suggest.Suggestion.Entry.Option): String {return hit.text}

例如需要自动补全 "c",result 结构如下

1.4、ElasticsearchRepository

1.4.1、使用方式

这个东西就跟 JPA 的使用方式一样,只不过高版本的 SpringData Elasticsearch 没有给 ElasticsearchRepository 接口提供复杂搜索查询,建议还是使用 ElasticsearchTemplate

自定义一个接口, 继承  ElasticsearchRepository 接口,如下:

import org.cyk.dataes.model.AlbumInfoDo
import org.springframework.data.elasticsearch.repository.ElasticsearchRepositoryinterface AlbumInfoRepo: ElasticsearchRepository<AlbumInfoDo, Long> //<实体类,主键类型>

1.4.2、简单的增删改查

import org.cyk.dataes.model.AlbumInfoDo
import org.cyk.dataes.service.AlbumInfoESRepo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import javax.annotation.Resource@SpringBootTest(classes = [DataEsApplication::class])
class RepoTests {@Resource private lateinit var albumInfoESRepo: AlbumInfoESRepo@Testfun testSave() {//增加单个val a = AlbumInfoDo(1, 10000, "今天天气真好", "学习完之后,我要出去好好玩")val result = albumInfoESRepo.save(a)println(result)//批量新增val list = listOf(AlbumInfoDo(2, 10000, "西安六号线避雷", "前俯后仰。他就一直在那前后动。他背后是我朋友,我让他不要挤了,他直接就急了,开始故意很大力的挤来挤去。"),AlbumInfoDo(3, 10000, "字节跳动快上车~", "#内推 #字节跳动内推 #互联网"),AlbumInfoDo(4, 10000, "连王思聪也变得低调老实了", "如今的王思聪,不仅交女友的质量下降,在网上也不再像以前那样随意喷这喷那。显然,资金的紧张让他低调了许多"))val resultList = albumInfoESRepo.saveAll(list)resultList.forEach(::println)}@Testfun testDel() {//根据 id 删除albumInfoESRepo.deleteById(1)//删除所有albumInfoESRepo.deleteAll()}@Testfun testFind() {//查询所有val resultList = albumInfoESRepo.findAll()resultList.forEach(::println)//根据 id 查询val result = albumInfoESRepo.findById(1)println(result.get())}}

1.4.3、分页排序查询

import org.cyk.dataes.service.AlbumInfoESRepo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import javax.annotation.Resource@SpringBootTest(classes = [DataEsApplication::class])
class RepoTests2 {@Resourceprivate lateinit var albumInfoESRepo: AlbumInfoESRepo@Testfun testFindPageAndSort() {//从 0 下标开始向后获取 3 个,并根据 id 降序排序val result = albumInfoESRepo.findAll(PageRequest.of(0, 3,Sort.by(Sort.Direction.DESC, "id")))result.content.forEach(::println)}}

相关文章:

SpringData ElasticSearch - 简化开发,完美适配 Spring 生态

目录 一、SpringData ElasticSearch 1.1、环境配置 1.2、创建实体类 1.3、ElasticsearchRestTemplate 的使用 1.3.1、创建索引 设置映射 1.3.2、创建索引映射注意事项&#xff08;必看&#xff09; 1.3.3、简单的增删改查 1.3.4、搜索 1.4、ElasticsearchRepository …...

突破!AI机器人拥有嗅觉!仿生嗅觉芯片研究登上Nature子刊

我们一直梦想着让AI与人类能够更加相似&#xff0c;赋予它们视觉与听觉。而让机器人拥有嗅觉一直以来面临着巨大的困难。 香港科技大学范志勇教授领导的研究团队凭借最新研发的仿生嗅觉芯片&#xff08;BOC&#xff09;在这一领域取得了重大突破。该研究成果目前已被发表到IF …...

前端接口防止重复请求实现方案

前言 前段时间老板心血来潮&#xff0c;要我们前端组对整个的项目都做一下接口防止重复请求的处理&#xff08;似乎是有用户通过一些快速点击薅到了一些优惠券啥的&#xff09;。。。听到这个需求&#xff0c;第一反应就是&#xff0c;防止薅羊毛最保险的方案不还是在服务端加…...

【leetcode面试经典150题】13.除自身以外数组的乘积(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…...

网络编程核心概念解析:IP地址、端口号与网络字节序深度探讨

⭐小白苦学IT的博客主页 ⭐初学者必看&#xff1a;Linux操作系统入门 ⭐代码仓库&#xff1a;Linux代码仓库 ❤关注我一起讨论和学习Linux系统 本节重点 认识IP地址, 端口号, 网络字节序等网络编程中的基本概念; 1.前言 网络编程&#xff0c;作为现代信息社会中的一项核心技术&…...

突破编程_C++_网络编程(TCPIP 四层模型(网络层(1))

1 网络层概述 TCP/IP 四层模型中的网络层是模型中的核心组成部分&#xff0c;它主要负责处理数据包的路由和转发&#xff0c;确保数据能够在源主机和目标主机之间准确地传输。 一、主要功能 网络层的主要功能是实现数据包的选路和转发。当数据从应用层传输到传输层后&#x…...

Java | Leetcode Java题解之第9题回文数

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isPalindrome(int x) {// 特殊情况&#xff1a;// 如上所述&#xff0c;当 x < 0 时&#xff0c;x 不是回文数。// 同样地&#xff0c;如果数字的最后一位是 0&#xff0c;为了使该数字为回文&#xff0…...

极简云验证 download.php 文件读取漏洞复现

0x01 产品简介 极简云验证是一款开源的网络验证系统&#xff0c;支持多应用卡密生成&#xff1a;卡密生成 单码卡密 次数卡密 会员卡密 积分卡密、卡密管理 卡密长度 卡密封禁 批量生成 批量导出 自定义卡密前缀等&#xff1b;支持多应用多用户管理&#xff1a;应用备注 应用版…...

红黑树路径长度分析:证明与实现

红黑树路径长度分析&#xff1a;证明与实现 一、红黑树的基本性质二、证明&#xff1a;最长路径至多是最短路径的2倍2.1 证明思路2.2 证明过程 三、伪代码实现四、 C语言代码实现5、 结论 红黑树作为一种高效的自平衡二叉搜索树&#xff0c;在计算机科学领域中被广泛应用于各种…...

esp32 gpio初识(一)

目录 功能介绍 实操 功能介绍 引脚又叫管脚&#xff0c;英文叫 Pin, 就是从集成电路&#xff08;芯片以及一些电子元件&#xff09;内部电路引出与外围电路的接线的接口。 在我们的 ESP32 开发板上, 我们可以把这些称为引脚, 这些引脚其实是从 ESP32 芯片内部引出来的, 我们…...

python 自制黄金矿工游戏(设计思路+源码)

1.视频效果演示 python自制黄金矿工&#xff0c;细节拉满沉浸式体验&#xff0c;看了你也会 2.开发准备的工具 python3.8, pygame库(python3.5以上的版本应该都可以) 图片处理工具&#xff0c;美图秀秀 截图工具&#xff0c;电脑自带的 自动抠图网页&#xff1a;https://ko…...

Splunk Attack Range:一款针对Splunk安全的模拟测试环境创建工具

关于Splunk Attack Range Splunk Attack Range是一款针对Splunk安全的模拟测试环境创建工具&#xff0c;该工具完全开源&#xff0c;目前由Splunk威胁研究团队负责维护。 该工具能够帮助广大研究人员构建模拟攻击测试所用的本地或云端环境&#xff0c;并将数据转发至Splunk实例…...

OpenCV入门例程:裁剪图片、模糊检测、黑屏检测

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 本例程运行环境为CentOS7&…...

opencv-python库 cv2边界填充resize图片

文章目录 边界填充改变图片大小 边界填充 在OpenCV中&#xff0c;边界填充&#xff08;Border Padding&#xff09;是指在图像周围添加额外的像素&#xff0c;以扩展图像的尺寸或满足某些算法&#xff08;如卷积&#xff09;的要求。OpenCV提供了cv2.copyMakeBorder()函数来进…...

Java代码基础算法练习-负数个数统计-2024.04.04

任务描述&#xff1a; 从键盘输入任意10个整型数&#xff08;数值范围-100000~100000&#xff09;&#xff0c;统计其中的负数个数 任务要求&#xff1a; 代码示例&#xff1a; package April_2024;import java.util.Scanner;// 从键盘输入任意10个整型数&#xff08;数值范围…...

【算法刷题day17】Leetcode:110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和

110.平衡二叉树 文档链接&#xff1a;[代码随想录] 题目链接&#xff1a;:110.平衡二叉树 题目&#xff1a; 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 注意&#xff1a; 判断两棵子树高度差是否大于1 class Solution { public:int result;bool isBalanced(TreeNode…...

C++ | Leetcode C++题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isMatch(string s, string p) {int m s.size();int n p.size();auto matches [&](int i, int j) {if (i 0) {return false;}if (p[j - 1] .) {return true;}return s[i - 1] p[j - 1];};vector<…...

职场迷航?MBTI测试为你指明方向,找到最匹配的职业!

MBTI简介 MBTI的全名是Myers-Briggs Type Indicator。它是一种迫选型、自我报告式的性格评估工具&#xff0c;用以衡量和描述人们在获取信息、作出决策、对待生活等方面的心理活动规律和性格类型。 类型指标 美国的凯恩琳布里格斯和她的女儿伊莎贝尔布里格斯迈尔斯研制了迈尔…...

hive 慢sql 查询

hive 慢sql 查询 查找 hive 执行日志存储路径&#xff08;一般是 hive-audit.log &#xff09; 比如&#xff1a;/var/log/Bigdata/audit/hive/hiveserver/hive-audit.log 解析日志 获取 执行时间 执行 OperationId 执行人 UserNameroot 执行sql 数据分隔符为 \001 并写入 hiv…...

Vue - 2( 10000 字 Vue 入门级教程)

一&#xff1a;Vue 1.1 绑定样式 1.1.1 绑定 class 样式 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>绑定样式</title><style>......</style><script type"text/javascript" src&…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...