springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解,本文主要从小微型公司业务出发,选择meilisearch来作为项目的全文搜索引擎,还可以当成来mongodb来使用。

二、starter封装

1、项目结构展示

2、引入依赖包

    <dependencies><dependency><groupId>cn.iocoder.boot</groupId><artifactId>yudao-common</artifactId></dependency><!-- meilisearch 轻量级搜索       --><!-- https://mvnrepository.com/artifact/com.meilisearch.sdk/meilisearch-java --><dependency><groupId>com.meilisearch.sdk</groupId><artifactId>meilisearch-java</artifactId><version>0.11.2</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.40</version><scope>provided</scope></dependency><!-- Web 相关 --><dependency><groupId>cn.iocoder.boot</groupId><artifactId>yudao-spring-boot-starter-web</artifactId><scope>provided</scope> <!-- 设置为 provided,只有 OncePerRequestFilter 使用到 --></dependency></dependencies>

3、yml参数读取代码参考

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;/*** MeiliSearch 自动装配参数类* 2023年9月21日*/
@ConfigurationProperties("yudao.meilisearch")
@Data
@Validated
public class MeiliSearchProperties {/*** 主机地址*/private String hostUrl = "";/*** 接口访问标识*/private String apiKey = "123456";}

4、自动配置类代码参考

import com.meilisearch.sdk.Client;
import com.meilisearch.sdk.Config;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;import javax.annotation.Resource;/*** MeiliSearch 自动装配类* 2023年9月21日*/
@AutoConfiguration
@EnableConfigurationProperties({MeiliSearchProperties.class})
@EnableCaching
public class MeiliSearchAutoConfiguration {@ResourceMeiliSearchProperties properties;@Bean@ConditionalOnMissingBean(Client.class)Client client() {return new Client(config());}@Bean@ConditionalOnMissingBean(Config.class)Config config() {return new Config(properties.getHostUrl(), properties.getApiKey());}}

5、数据处理类参考

import com.meilisearch.sdk.json.GsonJsonHandler;import java.util.List;/*** MeiliSearch json解析类* 2023年9月21日*/
public class JsonHandler {private com.meilisearch.sdk.json.JsonHandler jsonHandler = new GsonJsonHandler();public <T> SearchResult<T> resultDecode(String o, Class<T> clazz) {Object result = null;try {result = jsonHandler.decode(o, SearchResult.class, clazz);} catch (Exception e) {e.printStackTrace();}return result == null ? null : (SearchResult<T>) result;}public <T> List<T> listDecode(Object o, Class<T> clazz) {Object list = null;try {list = jsonHandler.decode(o, List.class, clazz);} catch (Exception e) {e.printStackTrace();}return list == null ? null : (List<T>) list;}public String encode(Object o) {try {return jsonHandler.encode(o);} catch (Exception e) {e.printStackTrace();return null;}}public <T> T decode(Object o, Class<T> clazz) {T t = null;try {t = jsonHandler.decode(o, clazz);} catch (Exception e) {e.printStackTrace();}return t;}
}import java.util.List;
import java.util.Map;/*** MeiliSearch* 2023年9月21日*/
public class MatchedBean<T> {private T _formatted;private Map<String, List<Matching>> _matchesInfo;public T get_formatted() {return _formatted;}public void set_formatted(T _formatted) {this._formatted = _formatted;}public Map<String, List<Matching>> get_matchesInfo() {return _matchesInfo;}public void set_matchesInfo(Map<String, List<Matching>> _matchesInfo) {this._matchesInfo = _matchesInfo;}private class Matching {long start;long length;public long getStart() {return start;}public void setStart(long start) {this.start = start;}public long getLength() {return length;}public void setLength(long length) {this.length = length;}}
}import java.util.List;/*** MeiliSearch* 2023年9月21日*/
public class SearchResult<T> {private String query;private long offset;private long limit;private long processingTimeMs;private long nbHits;private boolean exhaustiveNbHits;private List<T> hits;public String getQuery() {return query;}public void setQuery(String query) {this.query = query;}public long getOffset() {return offset;}public void setOffset(long offset) {this.offset = offset;}public long getLimit() {return limit;}public void setLimit(long limit) {this.limit = limit;}public long getProcessingTimeMs() {return processingTimeMs;}public void setProcessingTimeMs(long processingTimeMs) {this.processingTimeMs = processingTimeMs;}public long getNbHits() {return nbHits;}public void setNbHits(long nbHits) {this.nbHits = nbHits;}public boolean isExhaustiveNbHits() {return exhaustiveNbHits;}public void setExhaustiveNbHits(boolean exhaustiveNbHits) {this.exhaustiveNbHits = exhaustiveNbHits;}public List<T> getHits() {return hits;}public void setHits(List<T> hits) {this.hits = hits;}@Overridepublic String toString() {return "SearchResult{" +"query='" + query + '\'' +", offset=" + offset +", limit=" + limit +", processingTimeMs=" + processingTimeMs +", nbHits=" + nbHits +", exhaustiveNbHits=" + exhaustiveNbHits +", hits=" + hits +'}';}
}

6、自定义注解代码参考

import java.lang.annotation.*;/*** MeiliSearch* 2023年9月21日*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MSFiled {/*** 是否开启过滤*/boolean openFilter() default false;/*** 是否不展示*/boolean noDisplayed() default false;/*** 是否开启排序*/boolean openSort() default false;/***  处理的字段名*/String key() ;
}import java.lang.annotation.*;/*** MeiliSearch* 2023年9月21日*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MSIndex {/*** 索引*/String uid() default "";/*** 主键*/String primaryKey() default "";/*** 分类最大数量*/int maxValuesPerFacet() default 100;/***  单次查询最大数量*/int maxTotalHits() default 1000;
}

7、基础操作接口封装

import cn.iocoder.yudao.framework.meilisearch.json.SearchResult;
import com.meilisearch.sdk.SearchRequest;
import com.meilisearch.sdk.model.Settings;
import com.meilisearch.sdk.model.Task;
import com.meilisearch.sdk.model.TaskInfo;import java.util.List;/*** MeiliSearch 基础接口* 2023年9月21日*/
interface DocumentOperations<T> {T get(String identifier);List<T> list();List<T> list(int limit);List<T> list(int offset, int limit);long add(T document);long update(T document);long add(List<T> documents);long update(List<T> documents);long delete(String identifier);long deleteBatch(String... documentsIdentifiers);long deleteAll();SearchResult<T> search(String q);SearchResult<T> search(String q, int offset, int limit);SearchResult<T> search(SearchRequest sr);Settings getSettings();TaskInfo updateSettings(Settings settings);TaskInfo resetSettings();Task getUpdate(int updateId);
}

8、基本操作实现

import cn.iocoder.yudao.framework.meilisearch.json.JsonHandler;
import cn.iocoder.yudao.framework.meilisearch.json.MSFiled;
import cn.iocoder.yudao.framework.meilisearch.json.MSIndex;
import cn.iocoder.yudao.framework.meilisearch.json.SearchResult;
import com.alibaba.fastjson2.JSON;
import com.meilisearch.sdk.*;
import com.meilisearch.sdk.model.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;/*** MeiliSearch 基本操作实现* 2023年9月21日*/
public class MeilisearchRepository<T> implements InitializingBean, DocumentOperations<T> {private Index index;private Class<T> tClass;private JsonHandler jsonHandler = new JsonHandler();@Resourceprivate Client client;@Overridepublic T get(String identifier) {T document;try {document = index.getDocument(identifier, tClass);} catch (Exception e) {throw new RuntimeException(e);}return document;}@Overridepublic List<T> list() {List<T> documents;try {documents = Optional.ofNullable(index.getDocuments(tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic List<T> list(int limit) {List<T> documents;try {DocumentsQuery query = new DocumentsQuery();query.setLimit(limit);documents = Optional.ofNullable(index.getDocuments(query, tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic List<T> list(int offset, int limit) {List<T> documents;try {DocumentsQuery query = new DocumentsQuery();query.setLimit(limit);query.setOffset(offset);documents = Optional.ofNullable(index.getDocuments(query, tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic long add(T document) {List<T> list = Collections.singletonList(document);return add(list);}@Overridepublic long update(T document) {List<T> list = Collections.singletonList(document);return update(list);}@Overridepublic long add(List documents) {int taskId;try {taskId = index.addDocuments(JSON.toJSONString(documents)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long update(List documents) {int updates;try {updates = index.updateDocuments(JSON.toJSONString(documents)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return updates;}@Overridepublic long delete(String identifier) {int taskId;try {taskId = index.deleteDocument(identifier).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long deleteBatch(String... documentsIdentifiers) {int taskId;try {taskId = index.deleteDocuments(Arrays.asList(documentsIdentifiers)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long deleteAll() {int taskId;try {taskId = index.deleteAllDocuments().getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic cn.iocoder.yudao.framework.meilisearch.json.SearchResult<T> search(String q) {String result;try {result = JSON.toJSONString(index.search(q));} catch (Exception e) {throw new RuntimeException(e);}return jsonHandler.resultDecode(result, tClass);}@Overridepublic cn.iocoder.yudao.framework.meilisearch.json.SearchResult<T> search(String q, int offset, int limit) {SearchRequest searchRequest = SearchRequest.builder().q(q).offset(offset).limit(limit).build();return search(searchRequest);}@Overridepublic SearchResult<T> search(SearchRequest sr) {String result;try {result = JSON.toJSONString(index.search(sr));} catch (Exception e) {throw new RuntimeException(e);}return jsonHandler.resultDecode(result, tClass);}@Overridepublic Settings getSettings() {try {return index.getSettings();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic TaskInfo updateSettings(Settings settings) {try {return index.updateSettings(settings);} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic TaskInfo resetSettings() {try {return index.resetSettings();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic Task getUpdate(int updateId) {try {return index.getTask(updateId);} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic void afterPropertiesSet() throws Exception {initIndex();}public Index getIndex() {return index;}/*** 初始化索引信息** @throws Exception*/private void initIndex() throws Exception {Class<? extends MeilisearchRepository> clazz = getClass();tClass = (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];MSIndex annoIndex = tClass.getAnnotation(MSIndex.class);String uid = annoIndex.uid();String primaryKey = annoIndex.primaryKey();if (StringUtils.isEmpty(uid)) {uid = tClass.getSimpleName().toLowerCase();}if (StringUtils.isEmpty(primaryKey)) {primaryKey = "id";}int maxTotalHit=1000;int maxValuesPerFacet=100;if (Objects.nonNull(annoIndex.maxTotalHits())){maxTotalHit=annoIndex.maxTotalHits();}if (Objects.nonNull(annoIndex.maxValuesPerFacet())){maxValuesPerFacet=100;}List<String> filterKey = new ArrayList<>();List<String> sortKey = new ArrayList<>();List<String> noDisPlay = new ArrayList<>();//获取类所有属性for (Field field : tClass.getDeclaredFields()) {//判断是否存在这个注解if (field.isAnnotationPresent(MSFiled.class)) {MSFiled annotation = field.getAnnotation(MSFiled.class);if (annotation.openFilter()) {filterKey.add(annotation.key());}if (annotation.openSort()) {sortKey.add(annotation.key());}if (annotation.noDisplayed()) {noDisPlay.add(annotation.key());}}}Results<Index> indexes = client.getIndexes();Index[] results = indexes.getResults();Boolean isHaveIndex=false;for (Index result : results) {if (uid.equals(result.getUid())){isHaveIndex=true;break;}}if (isHaveIndex){client.updateIndex(uid,primaryKey);this.index = client.getIndex(uid);Settings settings = new Settings();settings.setDisplayedAttributes(noDisPlay.size()>0?noDisPlay.toArray(new String[noDisPlay.size()]):new String[]{"*"});settings.setFilterableAttributes(filterKey.toArray(new String[filterKey.size()]));settings.setSortableAttributes(sortKey.toArray(new String[sortKey.size()]));index.updateSettings(settings);}else {client.createIndex(uid, primaryKey);}}
}

9、指定自动配置类所在

10、项目有统一版本管理的设置下版本管理

二、项目引用

1、引入starter依赖(没有版本统一管理的要把version加上)

2、基本使用

2.1、建立索引(宽表)

import cn.iocoder.yudao.framework.meilisearch.json.MSFiled;
import cn.iocoder.yudao.framework.meilisearch.json.MSIndex;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@MSIndex(uid = "com_baidu_main", primaryKey = "id")
public class MainDO {private Long id;private String seedsName;@MSFiled(openFilter = true, key = "isDelete")private Integer isDelete;@MSFiled(openFilter = true, key = "status")private Integer status;@MSFiled(openFilter = true, key = "classFiledId")private Integer classFiledId;private String classFiledName;@MSFiled(openFilter = true, key = "tags")private List<TageInfo> tags;
}

2.2、集成starter里边的mapper对milisearch进行基本操作

import cn.iocoder.yudao.framework.meilisearch.core.MeilisearchRepository;
import org.springframework.stereotype.Repository;@Repository
public class MeiliSearchMapper extends MeilisearchRepository<MainDO> {
}

2.3、基本使用

@Resource
private MeiliSearchMapper meiliSearchMapper;//根据标签分页查询
SearchRequest searchRequest4 = SearchRequest.builder().limit(pageParam.getPageSize().intValue()).sort(new String[]{"createTime:desc"}).offset(pageParam.getPageNo().intValue() == 0 ? pageParam.getPageNo().intValue() : (pageParam.getPageNo().intValue() - 1) * pageParam.getPageSize().intValue()).filter(new String[]{"tags.id=" + "10010" + " AND status=1 AND isDelete=0"}).build();
SearchResult<MainDO> search4 = meiliSearchMapper.search(searchRequest4);//保存Or编辑
List<SeedsDO> articleCardDTOS = new ArrayList<>();
Boolean aBoolean = meiliSearchMapper.add(articleCardDTOS) > 0 ? Boolean.TRUE : Boolean.FALSE;
//按id删除
meiliSearchMapper.delete(String.valueOf(10085));//根据类目分页查询
SearchRequest searchRequest3 = SearchRequest.builder().limit(pageParam.getPageSize().intValue()).offset(pageParam.getPageNo().intValue() == 0 ? pageParam.getPageNo().intValue() : (pageParam.getPageNo().intValue() - 1) * pageParam.getPageSize().intValue()).build();
StringBuffer sb1 = new StringBuffer();
sb.append("status =1 AND isDelete=0").append(" AND ").append("categoryId =").append(10086L);
searchRequest.setFilter(new String[]{sb.toString()});
searchRequest.setSort(new String[]{"createTime:desc"});
SearchResult<SeedsDO> search3 = meiliSearchMapper.search(searchRequest3);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/141961.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于图像形态学处理的路面裂缝检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...................................................... %1&#xff1a;从文件夹中读取多个…

spring的ThreadPoolTaskExecutor装饰器传递调用线程信息给线程池中的线程

概述 需求是想在线程池执行任务的时候&#xff0c;在开始前将调用线程的信息传到子线程中&#xff0c;在子线程完成后&#xff0c;再清除传入的数据。 下面使用了spring的ThreadPoolTaskExecutor来实现这个需求. ThreadPoolTaskExecutor 在jdk中使用的是ThreadPoolExecutor…

asp.net企业生产管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 企业生产管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 二、功能介绍 (1)用户管理&…

C# OpenCvSharp 基于直线检测的文本图像倾斜校正

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenCvSharp_基于直线检测的文…

Linux基础指令(五)

目录 前言1. 打包和压缩1.1 是什么1.2 为什么1.3 怎么办&#xff1f; 2. zip & unzip3. tar 指令结语&#xff1a; 前言 欢迎各位伙伴来到学习 Linux 指令的 第五天&#xff01;&#xff01;&#xff01; 在上一篇文章 Linux基本指令(四) 当中&#xff0c;我们学习了 fin…

C语言入门Day_25 函数与指针小结

目录 前言&#xff1a; 1.函数 2.指针 3.易错点 4.思维导图 前言&#xff1a; 函数就像一个“有魔法的加工盒”&#xff0c;你从入口丢一些原材料进去&#xff0c;它就能加工出一个成品。不同的函数能加工出不同的成品。 入口丢进去的瓶子&#xff0c;水和标签就是输入&a…

【服务端 | Redis】如何使用redis 有序集合实现股票交易的订单表(价格优先、时间优先)

前两天倒腾redis的有序集合时&#xff0c;自己发现了一个问题&#xff0c;redis的有序集合在score相同的情况 下是如何排序的&#xff1f; 通过谷歌搜索&#xff0c;发现了一些线索&#xff0c;在score相同的情况下&#xff0c;redis使用字典排序&#xff0c;不过不是太明白什…

计算机网络相关知识点(二)

TCP如何保证传输过程的可靠性&#xff1f; 校验和&#xff1a;发送方在发送数据之前计算校验和&#xff0c;接收方收到数据之后同样需要计算&#xff0c;如果不一致&#xff0c;那么代表传输有问题。 确认应答序&#xff0c;序列号&#xff1a;TCP进行传输时数据都进行了编号…

排查内存泄露

1 通过Performance确认是否存在内存泄露 一个存在内存泄露的 DEMO 代码&#xff1a; App.vue <template><div><button click"myFn" style"width: 200px; height: 200px;"></button><home v-if"ishow"></hom…

Xcode15下载iOS17一直中断解决办法

1、问题描述 目前的 xcode 15 安装时&#xff0c;跟以前有个差别&#xff1a;以往的 xcode 安装时自带了 ide、sdk 等工具包&#xff0c;安装后即可开始开发&#xff0c;而最新的包则被分开成了不同的包&#xff0c;这里以 ios 开发包为例&#xff1a;Xcode_15.xip 和 iOS_17_…

软件测试之敏捷项目风险管理

敏捷项目管理是近年来最为流行的项目管理方式之一。这主要归功于敏捷管理的特点&#xff1a;尽早交付、持续改进、灵活管理、团队投入、充分测试。它能充分利用测试周期&#xff0c;并监测每个测试过程中容易出现的问题&#xff0c;加快项目迭代速度&#xff0c;从而推进项目高…

docker 配置 gpu版pytorch环境--部署缺陷检测--Anomalib

目录 一、docker 配置 gpu版pyhorch环境1、显卡驱动、cuda版本、pytorch cuda版本三者对应2、拉取镜像 二、部署Anomalib1、下载Anomalib2、创建容器并且运行3、安装Anomalib进入项目路径安装依赖测试&#xff1a; 一、docker 配置 gpu版pyhorch环境 1、显卡驱动、cuda版本、p…

《优化接口设计的思路》系列:第四篇—接口的权限控制

系列文章导航 《优化接口设计的思路》系列&#xff1a;第一篇—接口参数的一些弯弯绕绕 《优化接口设计的思路》系列&#xff1a;第二篇—接口用户上下文的设计与实现 《优化接口设计的思路》系列&#xff1a;第三篇—留下用户调用接口的痕迹 《优化接口设计的思路》系列&#…

ROS2 从头开始:第 08/8回 - 使用 ROS2 生命周期节点简化机器人软件组件管理

一、说明 欢迎来到我在 ROS2 上的系列的第八部分。对于那些可能不熟悉该系列的人,我已经涵盖了一系列主题,包括 ROS2 简介、如何创建发布者和订阅者、自定义消息和服务创建、

02 MIT线性代数-矩阵消元 Elimination with matrices

一, 消元法 Method of Elimination 消元法是计算机软件求解线形方程组所用的最常见的方法。任何情况下&#xff0c;只要是矩阵A可逆&#xff0c;均可以通过消元法求得Axb的解 eg: 我们将矩阵左上角的1称之为“主元一”&#xff08;the first pivot&#xff09;&#xff0c;第…

【springboot3.x 记录】关于Jakarta包无法引入的问题

最近想将一些项目升级到springboot3.x和java17的时候&#xff0c;发现项目依赖中有Jakarta的包&#xff0c;但是代码标红提示没有相关的类&#xff0c;特此记录一下排查问题和最终解决问题的思路方法 一、发现问题 因为之前有创建过 springboot3.x java17 的项目&#xff0c;…

第6讲:v-for使用

目录 1.循环遍历 2.v-for遍历整形变量&#xff08;99乘法表&#xff09; 3.v-for遍历普通数组 4.v-for遍历数组对象 1.循环遍历 v-for指令基于一个数组渲染一个列表&#xff0c;它和JavaScript的遍历语法相似&#xff1a; v-for”item in list” list 是一个数组&#xff0c; i…

指针笔试题讲解

文章目录 题目答案与解析1、234、5、6、7、8、 题目 int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; }//由于还没学习结构体&#xff0c;这里告知结构体的大小是20个字节 //由于还没学习结…

2023-09-25 LeetCode每日一题(LFU 缓存)

2023-09-25每日一题 一、题目编号 460. LFU 缓存二、题目链接 点击跳转到题目位置 三、题目描述 请你为 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始…

腾讯mini项目-【指标监控服务重构】2023-08-25

今日已办 traefik proxy jaeger Prometheus prometheus | Prometheus 配置完依然无法实现 web-url的前缀访问【待解决】 Set span storage type : elasticsearch services:elasticsearch:image: elasticsearch:7.17.12container_name: elasticsearchnetworks:- backend # …