韵搜坊 -- Elastic Stack快速入门

文章目录

现有问题

搜索不够灵活,比如搜“无敌鸭小黑子”无法搜到“无敌鸭是小黑子”,因为MySQL的like是包含查询,需要分词搜索

Elastic Stack介绍(一套技术栈)

官网:https://www.elastic.co/cn/
各组件介绍:

  • beats套件:从各种不同类型的文件、应用中采集数据
  • logstash:从多个采集器或数据源来抽取,转换数据,向es输送
  • elasticsearch:存储,查询数据
  • kibana:可视化es的数据

安装ES

elastic search
介绍:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/setup.html
安装:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/zip-windows.html
image.png
注意,一套技术的版本都需要一致,这里都用7.17版本
启动:打开bin/elasticsearch.bat

安装Kibana

介绍:https://www.elastic.co/guide/en/kibana/7.17/introduction.html
安装:https://www.elastic.co/guide/en/kibana/7.17/install.html
启动:bin\kibana.bat,启动后cmd窗口会显示访问地址的

Elasticsearch概念

当成MySQL一样的数据库去学习和理解

倒排索引

正向索引:书籍的目录
倒排索引:根据内容找到文章
文章 A:你好,我是 rapper
文章 B:鱼皮你好,我是 coder

切词:
你好,我是,rapper
鱼皮,你好,我是,coder

构建倒排索引表:

内容 id
你好文章 A,B
我是文章 A,B
rapper文章 A
鱼皮文章 B
coder文章 B

用户搜:“鱼皮 rapper”
ES 先切词:鱼皮,rapper
然后去倒排索引表找对应的文章

Mapping

文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/explicit-mapping.html
可以理解为数据库的表结构,有哪些字段,字段类型
ES支持动态mapping,表结构可以动态改变,而不像MySQL一样没有的字段就不能插入
创建mapping:

GET user/_mappingPUT user
{"mappings": {"properties": {"age":    { "type": "integer" },  "email":  { "type": "keyword"  }, "name":   { "type": "text"  }     }}
}

分词器

指定了分词的规则
内置分词器:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-analyzers.html
分类
1)whitespace空格分词器,返回结果 The、quick、brown、fox.

POST _analyze
{"analyzer": "whitespace","text":     "The quick brown fox."
}

2)标准分词规则standard,返回结果:is、this、deja、vu

POST _analyze
{"tokenizer": "standard","filter":  [ "lowercase", "asciifolding" ],"text":      "Is this déja vu?"
}

3)关键词分词器:就是不分词,整句话当关键词,返回结果The quick brown fox.

POST _analyze
{"analyzer": "keyword","text":     "The quick brown fox."
}

IK分词器(ES插件)

官网:https://github.com/medcl/elasticsearch-analysis-ik
下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.17.7(注意版本一致)
优点:中文友好
ik_smart和ik_max_word的区别?举例:“小黑子”
ik_smart是智能分词,尽量选择最像一个词的拆分方式,比如"小",“黑子”
ik_max_word尽可能地分词,可以包括组合词,比如:“小黑”,“黑子”
使用步骤

  1. 在 elasticsearch-7.17.9 目录下新建 plugins 目录
  2. 在 plugins 目录下新建 ik 目录
  3. 将 elasticsearch-analysis-ik-7.17.7 目录中的所有内容移到 ik 目录下
  4. 重启es

报错
image.png
解决方案:https://github.com/medcl/elasticsearch-analysis-ik/issues/996
下载相近的版本,解压后修改plugin-descriptor.properties文件里面的elasticsearch.version就可以。
下面这两部分改为自己es的版本
image.png
安装成功
image.png

打分机制

比如有 3 条内容:
1)鱼皮是狗
2)鱼皮是小黑子
3)我是小黑子

用户搜索:
1)鱼皮,第一条分数最高,因为第一条匹配了关键词,而且更短(匹配比例更大)
2)鱼皮小黑子 => 鱼皮、小、黑子,排序结果:2 > 3 > 1
参考文章:https://liyupi.blog.csdn.net/article/details/119176943
官方参考文章:https://www.elastic.co/guide/en/elasticsearch/guide/master/controlling-relevance.html

ES的几种调用方式

restful api调用(http 请求)

GET请求:http://localhost:9200/
curl可以模拟发送请求:curl -X GET “localhost:9200/?pretty”
ES的启动端口

  1. 9200:给外部用户(给客户端调用)的端口
  2. 9300:给ES集群内部通信的(外部调用不了的)端口

kibana devtools

自由地对ES进行操作(本质也是 restful api)
devtools不建议生产环境使用
image.png

客户端调用

java客户端等
参考文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/_getting_started.html

ES的语法

DSL

DSL语法:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl.html
json格式,好理解,和http请求最兼容,应用最广,推荐!
建表,插入数据

POST post/_doc
{"title": "无敌鸭","desc": "无敌鸭描述"
}

查询全部

GET post/_search
{"query": {"match_all": { }}
}

根据id查询

GET post/_doc/GPaBZ48BMmF6cg2s9YSL

修改

POST post/_doc/GPaBZ48BMmF6cg2s9YSL
{"title": "无敌鸭修改","desc": "无敌鸭修改描述"
}

删除
删除普通索引
(注:es中的索引相当于MySQL中的表)

DELETE index_name

删除数据流式索引

DELETE _data_stream/logs-my_app-default

EQL

专门查询 ECS 文档(标准指标文档)的数据的语法,更加规范,但只适用于特定场景(比如事件流)
文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/eql.html
示例:

POST my_event/_doc
{"title": "鱼333333皮","@timestamp": "2099-05-06T16:21:15.000Z","event": {"original": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736"}
}GET my_event/_eql/search
{"query": """any where 1 == 1"""
}

SQL

文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/sql-getting-started.html
学习成本低,但是可能需要插件支持、性能较差
示例:

POST /_sql?format=txt
{"query": "SELECT * FROM post where title like '%鱼皮%'"
}

Painless Scripting language
编程取值,更灵活,但是学习成本高

Java 操作 ES

三种方式

1)ES 官方的Java API

https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/introduction.html
快速开始:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/connecting.html

2)ES 以前的官方Java API ,HighLevelRestClient(已废弃,不建议用)

3)Spring Data Elasticsearch(推荐)

spring-data系列:spring 提供的操作数据的框架
spring-data-redis:操作 redis 的一套方法
spring-data-mongodb:操作 mongodb 的一套方法
spring-data-elasticsearch:操作 elasticsearch 的一套方法

官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/

用ES实现搜索接口
Spring Data Elasticsearch方式

建表(建立索引)

数据库表结构

    content    text                               null comment '内容',tags       varchar(1024)                      null comment '标签列表(json 数组)',thumbNum   int      default 0                 not null comment '点赞数',favourNum  int      default 0                 not null comment '收藏数',userId     bigint                             not null comment '创建用户 id',createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',isDelete   tinyint  default 0                 not null comment '是否删除',index idx_userId (userId)
) comment '帖子' collate = utf8mb4_unicode_ci;

注意:

  • aliases: 别名(为了后续方便数据迁移)
  • 字段类型是text,这个字段是可被分词的,可模糊查询的;而如果是keyword,只能完全匹配,精确查询
  • analyzer(存储时生效的分词器):用ik_max_word,拆地更碎,索引更多,更有可能被搜出来
  • search_analyzer(查询时生效的分词器):用ik_smart,更偏向于用户想搜的分词
  • 如果想要让text类型的分词字段也支持精确查询,可以创建keyword类型的子字段
"fields": {"keyword": {"type": "keyword","ignore_above": 256 // 超过字符数则忽略查询}}

建表结构

PUT post_v1
{"aliases": {"post": {}},"mappings": {"properties": {"title": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"content": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"tags": {"type": "keyword"},"userId": {"type": "keyword"},"createTime": {"type": "date"},"updateTime": {"type": "date"},"isDelete": {"type": "keyword"}}}
}

增删改查(java使用es步骤,重要!)

步骤

  1. 引入jar包
<!-- elasticsearch-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
  1. 编写实体类

坐标:model/dto/post/PostEsDTO

package com.yupi.springbootinit.model.dto.post;import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.yupi.springbootinit.model.entity.Post;
import lombok.Data;import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.io.Serializable;
import java.util.Date;
import java.util.List;/*** 帖子 ES 包装类** * **/
// todo 取消注释开启 ES(须先配置 ES)
//@Document(indexName = "post")
@Data
public class PostEsDTO implements Serializable {private static final String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";/*** id*/@Idprivate Long id;/*** 标题*/private String title;/*** 内容*/private String content;/*** 标签列表*/private List<String> tags;/*** 点赞数*/private Integer thumbNum;/*** 收藏数*/private Integer favourNum;/*** 创建用户 id*/private Long userId;/*** 创建时间*/@Field(index = false, store = true, type = FieldType.Date, format = {}, pattern = DATE_TIME_PATTERN)private Date createTime;/*** 更新时间*/@Field(index = false, store = true, type = FieldType.Date, format = {}, pattern = DATE_TIME_PATTERN)private Date updateTime;/*** 是否删除*/private Integer isDelete;private static final long serialVersionUID = 1L;/*** 对象转包装类** @param post* @return*/public static PostEsDTO objToDto(Post post) {if (post == null) {return null;}PostEsDTO postEsDTO = new PostEsDTO();BeanUtils.copyProperties(post, postEsDTO);String tagsStr = post.getTags();if (StringUtils.isNotBlank(tagsStr)) {postEsDTO.setTags(JSONUtil.toList(tagsStr, String.class));}return postEsDTO;}/*** 包装类转对象** @param postEsDTO* @return*/public static Post dtoToObj(PostEsDTO postEsDTO) {if (postEsDTO == null) {return null;}Post post = new Post();BeanUtils.copyProperties(postEsDTO, post);List<String> tagList = postEsDTO.getTags();if (CollUtil.isNotEmpty(tagList)) {post.setTags(JSONUtil.toJsonStr(tagList));}return post;}
}
  1. 在application.xml中配置Elasticsearch
spring:elasticsearch:uris: http://localhost:9200username: rootpassword: 123456
  1. 启动项目(别忘了打开es)
  2. 使用es

1)方式一 : 继承ElasticsearchRepository<PostEsDTO, Long>这个类,默认提供了简单的增删改查,多用于可预期的,相对没那么复杂的查询,自定义查询,返回结果相对简单直接直接
接口代码:

public interface CrudRepository<T, ID> extends Repository<T, ID> {<S extends T> S save(S entity);<S extends T> Iterable<S> saveAll(Iterable<S> entities);Optional<T> findById(ID id);boolean existsById(ID id);Iterable<T> findAll();Iterable<T> findAllById(Iterable<ID> ids);long count();void deleteById(ID id);void delete(T entity);void deleteAllById(Iterable<? extends ID> ids);void deleteAll(Iterable<? extends T> entities);void deleteAll();
}

测试:
**添加数据 **

@Test
void testAdd() {PostEsDTO postEsDTO = new PostEsDTO();postEsDTO.setId(1L);postEsDTO.setTitle("测试添加数据标题");postEsDTO.setContent("测试添加数据内容");postEsDTO.setTags(Arrays.asList("java", "python"));postEsDTO.setThumbNum(1);postEsDTO.setFavourNum(1);postEsDTO.setUserId(1L);postEsDTO.setCreateTime(new Date());postEsDTO.setUpdateTime(new Date());postEsDTO.setIsDelete(0);postEsDao.save(postEsDTO);System.out.println(postEsDTO.getId());
}

查询数据
方式一:在kibana devtools里查
image.png
方式二:在java代码里查

    @Testvoid testSelect() {System.out.println(postEsDao.count());Page<PostEsDTO> PostPage = postEsDao.findAll(PageRequest.of(0, 5, Sort.by("createTime")));List<PostEsDTO> postList = PostPage.getContent(); //分页查询System.out.println(postList);Optional<PostEsDTO> byId = postEsDao.findById(1L); //根据id查询System.out.println(byId);}
  1. 添加自定义方法

坐标:esdao/PostEsDao
支持根据方法名自动生成方法,比如:

List<PostEsDTO> findByTitle(String title);

测试此方法:

@Test
void testFindByTitle() {List<PostEsDTO> postEsDTOS = postEsDao.findByTitle("测试添加数据标题");System.out.println(postEsDTOS);
}

根据他的命名规则写方法名,不用实现,就可以用了~(好神奇唉)

注意:ES中,_开头的字段表示系统默认字段,比如_id,如果系统不指定,会自动生成。但是不会在_source字段中补充id的值,所以建议大家手动指定。

2)方式二:Spring默认给我们提供操作es的客户端对象
ElasticsearchRestTemplate,也提供了增删改查,它的增删改查更灵活,适用于复杂度的操作,返回结果更完整,但需要自己解析,对于复杂的查询,建议使用该方式
三个步骤:

  1. 取参数
  2. 把参数组合为ES支持的搜索条件
  3. 从返回值中取结果

参考文档:

  • https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-filter-context.html
  • https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-bool-query.html

示例代码:

GET post/_search
{"query": { "bool": { // 组合条件"must": [ // 必须都满足{ "match": { "title":   "鱼皮"        }}, // match 模糊查询{ "match": { "content":   "知识星球"        }}],"filter": [ { "term":  { "status": "published" }}, // term 精确查询{ "range": { "publish_date": { "gte": "2015-01-01" }}} // range 范围查询]}}
}

wildcard 模糊查询
regexp 正则匹配查询
查询结果中,score 代表匹配分数
建议先测试 DSL、再翻译成 Java
DSL:

{"query": {"bool": {"must_not": [{"match": {"title": ""}},]"should": [{"match": {"title": ""}},{"match": {"desc": ""}}],"filter": [{"term": {"isDelete": 0}},{"term": {"id": 1}},{"term": {"tags": "java"}},{"term": {"tags": "框架"}}],"minimum_should_match": 0}},"from": 0, // 分页"size": 5, // 分页"_source": ["name", "_createTime", "desc", "reviewStatus", "priority", "tags"], // 要查的字段"sort": [ // 排序{"priority": {"order": "desc"}},{"_score": {"order": "desc"}},{"publishTime": {"order": "desc"}}]
}

翻译为Java:

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 过滤
boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
if (id != null) {boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
}
if (notId != null) {boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));
}
if (userId != null) {boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));
}
// 必须包含所有标签
if (CollectionUtils.isNotEmpty(tagList)) {for (String tag : tagList) {boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));}
}
// 包含任何一个标签即可
if (CollectionUtils.isNotEmpty(orTagList)) {BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();for (String tag : orTagList) {orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));}orTagBoolQueryBuilder.minimumShouldMatch(1);boolQueryBuilder.filter(orTagBoolQueryBuilder);
}
// 按关键词检索
if (StringUtils.isNotBlank(searchText)) {boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));boolQueryBuilder.minimumShouldMatch(1);
}
// 按标题检索
if (StringUtils.isNotBlank(title)) {boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));boolQueryBuilder.minimumShouldMatch(1);
}
// 按内容检索
if (StringUtils.isNotBlank(content)) {boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));boolQueryBuilder.minimumShouldMatch(1);
}
// 排序
SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
if (StringUtils.isNotBlank(sortField)) {sortBuilder = SortBuilders.fieldSort(sortField);sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
}
// 分页
PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
// 构造查询
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
.withPageable(pageRequest).withSorts(sortBuilder).build();
SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);

动静分离设计:先模糊筛选静态数据,查出数据后,再根据查到的内容 id 去数据库查找到 动态数据。
修改doSearch查询
坐标:com/yupi/springbootinit/datasource/PostDataSource

    @Overridepublic Page<PostVO> doSearch(String searchText, long pageNum, long pageSize) {PostQueryRequest postQueryRequest = new PostQueryRequest();postQueryRequest.setSearchText(searchText);postQueryRequest.setCurrent(pageNum);postQueryRequest.setPageSize(pageSize);HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();Page<Post> postPage = postService.searchFromEs(postQueryRequest);return postService.getPostVOPage(postPage,request);}
//searchFromEs方法就是上面翻译为java的代码方法

数据同步

需要将MySQL中的数据和ES中的数据进行同步

方式

全量同步一种方式,增量同步三种方式

  1. 全量同步

首次将MySQL的数据一次性导入到ES中

  1. 增量同步-定时任务

比如一分钟一次,找到MySQL过去几分钟有更新的数据,写入到ES

  1. 增量同步-双写

写数据库的时候,必须也写ES,更新删除同理(需要保证原子性)

  1. 增量同步–Logstash数据同步管道

( 一般要配合 kafka 消息队列 + beats 采集器 )

(1)Logstash

  1. Logstash介绍

“传输和处理信息的管道”
image.png

  1. 下载安装包

官方文档:https://www.elastic.co/guide/en/logstash/7.17/installing-logstash.html
下载地址:https://artifacts.elastic.co/downloads/logstash/logstash-7.17.9-windows-x86_64.zip

  1. 启动
cd logstash-7.17.9
.\bin\logstash.bat -e "input { stdin { } } output { stdout {} }"

遇到bug:系统找不到指定的路径。 could not find java; set JAVA_HOME or ensure java is in PATH
解决:将本地的JAVA_HOME环境变量名字改为它所推荐的LS_JAVA_HOME
image.png

  1. 快速开始:https://www.elastic.co/guide/en/logstash/7.17/running-logstash-windows.html

监听 udp 并输出:

input {udp {port => 514type => "syslog"}
}output {elasticsearch { hosts => ["localhost:9200"] }stdout { codec => rubydebug }
}

image.png

在mytask.conf文件中写入

input {udp {port => 514type => "syslog"}
}output {stdout { codec => rubydebug }
}

以该配置文件启动 Logstash,注意要进到bin目录下

logstash.bat -f ..\config\mytask.conf

image.png
证明已经监听udp了

(2)MySQL 同步给 Elasticsearch

将mysql的jar包放到配置文件中(jar包可以从idea的maven本地仓库中找)
image.png
修改mytask.conf文件:

input {jdbc {jdbc_driver_library => "D:\software\ElasticStack\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar"jdbc_driver_class => "com.mysql.jdbc.Driver"jdbc_connection_string => "jdbc:mysql://localhost:3306/my_db"jdbc_user => "root"jdbc_password => "dyz200472"statement => "SELECT * from post where updateTime > :sql_last_value and updateTime < now() order by updateTime desc"tracking_column => "updatetime"tracking_column_type => "timestamp"use_column_value => trueparameters => { "favorite_artist" => "Beethoven" }schedule => "*/5 * * * * *"jdbc_default_timezone => "Asia/Shanghai"}
}filter {mutate {rename => {"updatetime" => "updateTime""userid" => "userId""createtime" => "createTime""isdelete" => "isDelete"}remove_field => ["thumbnum", "favournum"]}
}output {stdout { codec => rubydebug }elasticsearch {hosts => "http://localhost:9200"index => "post_v1"document_id => "%{id}"}
}

注意:sql_last_value 是取上次查到的数据的最后一行的指定的字段,如果要全量更新,只要删除掉 E:\software\ElasticStack\logstash-7.17.9\data\plugins\inputs\jdbc\logstash_jdbc_last_run 文件即可(这个文件存储了上次同步到的数据),这里我删除了但是es上仍然没有更新数据,重启logstash好了
修改为es查询
image.png

(3) 订阅数据库流水的同步方式 Canal(未实现)

https://github.com/alibaba/canal/
数据库每次修改时,会修改binlog文件,只要监听该文件的修改,就能第一时间得到数据并修改
canal:帮你监听binlog,并且可以解析binlog为你理解的内容,它伪装成了mysql的从节点,获取主节点给的binlog
快速开始:https://github.com/alibaba/canal/wiki/QuickStart
windows 系统,找到你本地的 mysql 安装目录,在根目录下新建 my.ini 文件:

[mysqld]
log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义, 不要和 canal 的 slaveId 重复

如果 java 找不到,修改 startup.bat 脚本为你自己的 java home:

set JAVA_HOME=C:\Users\59278\.jdks\corretto-1.8.0_302
echo %JAVA_HOME%
set PATH=%JAVA_HOME%\bin;%PATH%
echo %PATH%

问题:mysql 无法链接,Caused by: java.io.IOException: caching_sha2_password Auth failed
解决方案: https://github.com/alibaba/canal/issues/3902
ALTER USER ‘canal’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘canal’; ALTER USER ‘canal’@‘%’ IDENTIFIED BY ‘canal’ PASSWORD EXPIRE NEVER; FLUSH PRIVILEGES;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员做推广?我劝你别干

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这是卢松松会员专区&#xff0c;一位会员朋友的咨询&#xff0c;如果你也有自研产品&#xff0c;但不知道如何推广&#xff0c;一定要阅读本文!强烈建议收藏关注&#xff0c;因为你关注的人&#xff0c;决定你看到的…

【机器学习300问】98、卷积神经网络中的卷积核到底有什么用?以边缘检测为例说明其意义。

卷积核是用于从输入数据中提取特征的关键工具。卷积核的设计直接关系到网络能够识别和学习的特征类型。本文让我以边缘检测为例&#xff0c;带大家深入理解卷积核的作用。 一、卷积核的作用 卷积核&#xff0c;又称为过滤器&#xff0c;本质上是一个小的矩阵&#xff0c;其元素…

微信小程序毕业设计-智慧旅游平台系统项目开发实战(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

【算法】二分算法——山脉数组的峰顶索引

该题用二分算法解“山脉数组的峰顶索引”&#xff0c;有需要借鉴即可。 目录 1.题目2.总结 1.题目 题目链接&#xff1a;LINK 暴力求解很简单&#xff0c;这里不再提及。 这个可以根据峰顶值分为两部分&#xff0c;因而具有“二段性”&#xff0c;可以用二分算法&#xff0c…

默认路由实现两个网段互通实验

默认路由实现两个网段互通实验 **默认路由&#xff1a;**是一种特殊的静态路由&#xff0c;当路由表中与数据包目的地址没有匹配的表项时&#xff0c;数据包将根据默认路由条目进行转发。默认路由在某些时候是非常有效的&#xff0c;例如在末梢网络中&#xff0c;默认路由可以…

Postgresql源码(133)优化器动态规划生成连接路径的实例分析

物理算子的生成分为两步&#xff0c;基表的扫描路径生成set_base_rel_pathlists&#xff1b;连接路径生成&#xff08;make_rel_from_joinlist动态规划&#xff09;。本篇简单分析实现。看过代码会发现&#xff0c;“基表的扫描路径生成”其实就是作为连接路径生成dp计算的第一…

【Mac】MWeb Pro(好用的markdown编辑器) v4.5.9中文版安装教程

软件介绍 MWeb Pro for Mac是一款Mac上的Markdown编辑器软件&#xff0c;它支持实时预览&#xff0c;语法高亮&#xff0c;自动保存和备份等功能&#xff0c;并且有多种主题和样式可供选择。此外&#xff0c;MWeb还支持多种导出格式&#xff0c;包括HTML、PDF、Word、ePub等&a…

栈和队列的经典例题,LeetCode 括号匹配问题;栈实现队列;队列实现栈;队列带环问题

1.前序 又有很久没有更新文章了&#xff0c;这次带你们手撕几道基础题&#xff1b;真的就和康纳吃饭一样简单&#xff01;&#xff01;&#xff01; 如果还不会队列和栈的可以去看看之前写的博客&#xff1b; 栈的实现 队列概念以及实现 <- 快速传送 目录 1.前序 …

自定义全局变量3

变量删除 语法 unset var_name演示 自定义常量 介绍 就是变量设置值以后不可以修改的变量叫常量, 也叫只读变量 语法 readonly var_name演示 自定义全局变量 父子Shell环境介绍 例如: 有2个Shell脚本文件 A.sh 和 B.sh 如果 在A.sh脚本文件中执行了B.sh脚本文件, 那么A.…

【Web】CISCN 2024初赛 题解(全)

目录 Simple_php easycms easycms_revenge ezjava mossfern sanic Simple_php 用php -r进行php代码执行 因为ban了引号&#xff0c;考虑hex2bin&#xff0c;将数字转为字符串 php -r eval(hex2bin(16进制)); 注意下面这段报错&#xff0c;因为加不了引号&#xff0c;开…

链表-设计LRU缓存结构

题目描述&#xff1a; 代码实现&#xff1a;这里记录了根据LRU算法原理最直接理解的代码实现。 import java.util.*;//存储输入内容&#xff0c;记录访问权值 class CounterInfo {int key;int value;int times;//代表key对应的权值&#xff0c;值越小优先级越高public Counter…

【第2章】SpringBoot配置文件

文章目录 前言一、编写配置信息1. properties2. yml 二、获取配置信息1.直接获取2.配置类形式 总结 前言 SpringBoot工程创建后&#xff0c;会为我们提供一个默认的配置文件(application.properties)&#xff0c;配置文件主要用于那些可能发生变化且经常改变的属性值。 一、编…

Autodesk 3DS Max v2025 解锁版安装教程 (3D 建模软件)

前言 Autodesk 3ds Max 是一款功能强大的 3D 建模和动画解决方案&#xff0c;游戏开发人员、视觉效果艺术家和平面设计师使用它来创建庞大的世界、令人惊叹的场景和引人入胜的虚拟现实 (VR) 体验。 Autodesk 3DS MAX是业界使用最广泛的3D建模和动画软件程序之一&#xff0c;它…

盲盒小程序开发,数字化发展下的优势

近年来&#xff0c;盲盒经济得到了快速发展&#xff0c;不少人开始加入到盲盒大军中&#xff0c;盲盒市场规模不断扩大。 盲盒最大的特点就是能够给消费者带来拆盒的刺激性和惊喜感。盲盒商品大多是动漫手办、周边等&#xff0c;具有较大的收藏价值&#xff0c;因此深深吸引着…

OpenAI模型GPT-4o、GPT-4、Gemini 1.5性能比较

大家好&#xff0c;OpenAI最新推出的GPT-4o&#xff0c;标志着人工智能语言模型和交互方式迈入了新纪元。最引人注目的是&#xff0c;GPT-4o支持实时互动和流畅的对话切换&#xff0c;让交流更加自然。 本文将对比分析GPT-4o、GPT 4以及谷歌的Gemini和Unicorn模型&#xff0c;…

JVM-调优之-如何使用arthas-观察jvm-cpu-内存-垃圾回收等信息

前言&#xff1a; 可以简单代替把dump文件下载下来后用visualvm分析了&#xff1b;跟visualvm类似的&#xff1b; docker中如何安装arthas看这个&#xff1a;docker中怎么使用arthas_arthas 集成到容器镜像-CSDN博客 curl -O https://arthas.aliyun.com/arthas-boot.jar wget …

软考之零碎片段记录(三十一)+复习巩固(错题整理,知识点总结,易错题)

1. 奇偶校验 只能检测一位数的错误。但无法纠正错误。若有奇数个数据位出错&#xff0c;可检测。有局限性。 2. 深度与广度优先遍历 参考题【【数据结构自用】1.图深度优先遍历2.找有向图中的强连通分量数目3.给出图的任意两个拓扑序列】https://www.bilibili.com/video/BV…

在Github上寻找安装ROS软件包

1、创建一个功能包 并下载git sudo apt install git 2、找到自己想在github上要克隆的包 复制此链接 3、克隆到本地 git clone 链接 4.scripts目录用于放置脚本文件和python程序 使用脚本安装编译需要的依赖库 5、下载完成后&#xff0c;在~catkin_ws目录下运行catkin_make进…

HTTP响应的基本概念

目录 HTTP响应中的一些信息 HTTPS HTTP响应中的一些信息 状态码&#xff1a;描述了这次HTTP请求是否成功&#xff0c;以及失败的原因。 1&#xff09;200 ---OK 表示这次访问成功了。 2&#xff09;404 ---Not Found 表示客户端请求的资源在服务器这边不存在。 3&a…

SRE视角下的DevOps:构建稳定高效的软件交付流程

SRE 和 DevOps 有什么区别和联系&#xff1f;本文对此进行了解读&#xff0c;并着重从 SRE 实践出发阐述了 DevOps 的建设思路。 SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的工作。SRE 的职责是运维一个服务&#xff0c;该服务由一些相关的系统组件…