第14天-ElasticSearch环境配置,构建检索服务及商品上架到ES库

news2024/11/26 6:00:48

1.ElasticSearch概念

在这里插入图片描述

官网介绍:https://www.elastic.co/cn/what-is/elasticsearch/

官网学习文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html



1.1.ElasticSearch与MySQL的比较

  • MySQL有事务性,而ElasticSearch没有事务性,所以你删了的数据是无法恢复的。
  • ElasticSearch没有物理外键这个特性,如果你的数据强一致性要求比较高,还是建议慎用
  • ElasticSearch和MySql分工不同, MySQL负责存储数据, ElasticSearch负责搜索数据

在这里插入图片描述



1.2.为什么要使用Elasticsearch?

因为在我们商城中的数据,将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会丢弃索引,导致商品查询是全表扫描,在百万级别的数据库中,效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度。



1.3.ES中核心概念

在这里插入图片描述



1.4.倒排索引机制

倒排索引:将各个文档中的内容,进行分词,形成词条。然后记录词条和数据的唯一标识(id)的对应关系,形成的产物 。

倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。倒排索引是一种像数据结构一样的散列图,可将用户从单词导向文档或网页。它是搜索引擎的核心。其主要目标是快速搜索从数百万文件中查找数据。

在这里插入图片描述



1.5.ElasticSearch数据的存储和搜索原理

在这里插入图片描述

在这里插入图片描述



2.Docker安装

Support Matrix:https://www.elastic.co/cn/support/matrix#matrix_compatibility

  • Elasticsearch 7.10.1 存储和检索数据
  • Kibana 7.10.1 可视化检索数据


2.1.下载镜像文件

docker pull elasticsearch:7.10.1 #存储和检索数据
docker pull kibana:7.10.1 #可视化检索数据



2.2.创建实例


2.2.1.ElasticSearch

# 查看虚拟机内存,建议调整到 4096m
free -m

mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
mkdir -p /mydata/elasticsearch/plugins

# 修改文件夹权限
chmod -R 777 /mydata/elasticsearch/

echo "http.host: 0.0.0.0">>/mydata/elasticsearch/config/elasticsearch.yml

# 9200 http请求端口,9300 集群节点之间通信端口
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
--restart=always \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms1024m -Xmx1024m" \
-v 
/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/el
asticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.10.1

# 查看容器启动日志
docker logs elasticsearch # 容器名或容器id都可以


访问:http://192.168.139.10:9200

在这里插入图片描述

查看es所有节点:http://192.168.229.116:9200/_cat/nodes

在这里插入图片描述

2.2.2.Kibana

# 注意:http://192.168.139.10:9200 为es的http访问地址
docker run --name kibana \
--restart=always \
-e ELASTICSEARCH_HOSTS=http://192.168.139.10:9200 \
-p 5601:5601 \
-d kibana:7.10.1


访问:http://192.168.139.10:5601

在这里插入图片描述

点击 Explore on my own

在这里插入图片描述



2.3.安装Nginx


2.3.1.复制配置

启动一个Nginx实例,复制出配置

docker run -p 80:80 --name nginx -d nginx:1.18.0

将容器内的配置文件拷贝到当前目录

cd /mydata
mkdir nginx
docker container cp nginx:/etc/nginx .

停止并删除容器

docker stop nginx
docker rm nginx

修改文件名称

mv nginx conf

mkdir nginx

mv conf/ nginx/


2.3.2. 创建实例

docker run -p 80:80 --name nginx \
--restart=always \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.18.0

2.3.3.访问测试

cd /mydata/nginx/html

vim index.html
<h1>com.atguigu.gmall<h1>

访问:http://192.168.139.10

在这里插入图片描述



3.文本分词

一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens(词元,通常是独立的单词),然后输出tokens流。

例如,whitespace tokenizer遇到空白字符时分割文本。它会将文本 Quick brown fox! 分割为
[Quick,brown,fox!] 。该tokenizer还负责记录各个 term(词条)的顺序或 position位置(用于
phrase短语和word proximity词近邻查询),以及term(词条)所代表的原始word(单词)的start(起始)和end(结束)的character offsets(字符偏移量),用于高亮显示搜索的内容。

ElasticSearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)。

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-tokenizer.html



3.1.安装ik分词器

GitHub:https://github.com/medcl/elasticsearch-analysis-ik

注意:ik分词器的版本一定要对应es版本安装


https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.10.1

# 进入 plugins 目录
cd /mydata/elasticsearch/plugins

# 下载
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.1/elasticsearch-analysis-ik-7.10.1.zip

# 解压
unzip elasticsearch-analysis-ik-7.10.1.zip -d ik

# 删除zip文件
rm -rf *.zip

# 修改ik文件夹权限
chmod -R 777 ik/

# 确认是否安装好了分词器,进入容器bin目录
docker exec -it elasticsearch /bin/bash
cd bin
# 列出系统的分词器
elasticsearch-plugin list
ik

# 重启容器
docker restart elasticsearch


3.2.测试分词器:

使用默认

GET _analyze
{
	"text":"我是中国人"
}

使用分词器 ik_smart

GET _analyze
{
	"analyzer":"ik_smart",
	"text":"我是中国人"
}

另一个分词器 ik_max_word

GET _analyze
{
	"analyzer":"ik_max_word",
	"text":"我是中国人"
}


3.3.自定义词库

配置远程词库,在nginx的 html 目录下新创建自定义词库

# 在html目录下创建es文件夹
mkdir es
# 创建新的分词并保存
vim participle.txt
尚硅谷
谷粒商城

修改 /mydata/elasticsearch/plugins/ik/config/ 中的 IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<!-- 用户可以在这里配置自己的扩展字典 ->
	<entry key="ext_dict"></entry>
	<!-- 用户可以在这里配置自己的扩展停止词字典->
	<entry key="ext_stopwords"></entry>
	<!-- 用户可以在这里配置远程扩展字典,这里使用的是nginx来访问 ->
	<entry key="remote_ext_dict">http://192.168.139.10/es/participle.txt</entry>
	<!-- 用户可以在这里配置远程扩展停止词字典->
	<!-- <entry key="remote_ext_stopwords">words_location</entry>->
</properties>

重启elasticsearch容器

docker restart elasticsearch



3.4.测试自定义词库

在这里插入图片描述

更新词库完成后,es只会对新增的数据用新词分词。历史数据是不会重新分词的,如果想要历史数据重新分词,需要执行:

POST my_index/_update_by_query?conflicts=proceed



4.创建检索服务模块


4.1ElasticSearch-Rest-Client

1)9300:TCP

spring-data-elasticsearch:transport-api.jar

  • Spring Boot 版本不同,transport-api.jar不同,不能适配 elasticsearch 版本
  • 官方7.x已经不建议使用,8以后就要废弃

2)9200:HTTP

  • JestClient:非官方,更新慢
  • RestTemplate:模拟发HTTP请求,ES很多操作需要自己封装,很麻烦
  • HttpClient/OkHttp:模拟发HTTP请求,ES很多操作需要自己封装,很麻烦
  • ElasticSearch-Rest-Client:官方RestClient封装了ES操作API层次分明上手简单

官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html



4.2.创建检索服务模块


4.2.1.新建Module gmall-search

1)聚合模块

<modules>
	<module>gmall-search</module>
</modules>

2)导入版本依赖
<properties>
	<elasticsearch.version>7.10.1</elasticsearch.version>
</properties>
<dependency>
	<groupId>com.atguigu.gmall</groupId>
    <artifactId>gmall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <exclusions>
        <exclusion>
        	<groupId>com.baomidou</groupId>
        	<artifactId>mybatis-plus-boot-starter</artifactId>
        </exclusion>
     	<exclusion>
         	<groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.elasticsearch.client</groupId>
	<artifactId>elasticsearch-rest-high-level-client</artifactId>
	<version>${elasticsearch.version}</version>
</dependency>

3)加入到Nacos注册中心和配置中心

application.yml

server:
  port: 20000
spring:
  application:
    name: gmall-search
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.139.10:8848
        namespace: 36854647-e68c-409b-9233-708a2d41702c

bootstrap.properties

spring.application.name=gmall-search
spring.cloud.nacos.config.server-addr=192.168.139.10:8848
spring.cloud.nacos.config.namespace=873d6587-5969-47dd-accb-a4d33a13817d
spring.cloud.nacos.config.group=dev

4)网关路由配置
spring:
  cloud:
    gateway:
      routes:
      - id: search_route
        uri: lb://gmall-search
        predicates:
        - Path=/api/search/**
        filters:
        - RewritePath=/api/(?<segment>.*), /$\{segment}

4.2.3.配置ElasticSearch

编写ElasticSearch配置类 ElasticSearchConfig

package com.atguigu.gmall.search.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * ElasticSearch 配置类 {@link ElasticSearchConfig}
 *  * @author zhangwen
 * @email: 1466787185@qq.com
 */
@Configuration
public class ElasticSearchConfig {

    public static final RequestOptions COMMON_OPTIONS;


    /**
     * https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low-usage-requests.html#java-rest-low-usage-request-options
     */
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        COMMON_OPTIONS = builder.build();
    }

    @Bean
    public RestHighLevelClient restHighLevelClient () {
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
                RestClient.builder(
                        // es集群模式下,可以指定多个 HttpHost
                        new HttpHost("192.168.139.10", 9200, "http")));

        return restHighLevelClient;
    }
}


# 5.商品上架到ES
  • 上架的商品才可以在网站展示

  • 上架的商品可以被检索



5.1.API

POST /product/spuinfo/{spuId}/up



5.2.后台接口实现

SpuInfoController

/**
 * 商品上架
 * @param spuId
 * @return
 */
 @PostMapping("/{spuId}/up")
 public R spuUp(@PathVariable("spuId") Long spuId) {
     spuInfoService.up(spuId);
     return R.ok();
 }

SpuInfoServiceImpl

/**
 * 商品上架
 * @param spuId
 */
@Override
public void up(Long spuId) {
    // 组装数据
    // 查询当前sku的所有可以被用来检索规格属性
    List<ProductAttrValueEntity> baseAttrs = productAttrValueService.listBaseAttrForSpu(spuId);
    List<Long> attrIds = baseAttrs.stream()
            .map(ProductAttrValueEntity::getAttrId)
            .collect(Collectors.toList());

    // 在指定的属性集合里面,查找出能够被检索的属性
    List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds);
    Set<Long> idSet = new HashSet<>(searchAttrIds);
    List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter(attr -> {
        return idSet.contains(attr.getAttrId());
    }).map(attr -> {
        SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
        BeanUtils.copyProperties(attr, attrs);
        return attrs;
    }).collect(Collectors.toList());

    // 查询出当前spuId对应的所有sku信息
    List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);
    // 发送远程调用,库存系统查询是否有库存
    List<Long> skuIds =
            skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
    Map<Long, Boolean> stockMap = null;
    try {
        List<SkuHasStockTO> tos = wareFeignService.getSkuHasStock(skuIds);
        stockMap = tos.stream().collect(
                Collectors.toMap(SkuHasStockTO::getSkuId, value ->
                        value.getHasStock()));
    } catch (Exception e) {
        log.error("调用远程库存服务 gmall-ware 查询异常:{}", e);
    }

    // 封装每个sku的信息
    Map<Long, Boolean> finalStockMap = stockMap;
    List<SkuEsModel> skuEsModelList = skus.stream().map(skuInfoEntity -> {
        SkuEsModel skuEsModel = new SkuEsModel();
        BeanUtils.copyProperties(skuInfoEntity, skuEsModel);
        skuEsModel.setSkuPrice(skuInfoEntity.getPrice());
        skuEsModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());

        // 远程调用异常,默认设置有库存
        if (finalStockMap == null) {
            skuEsModel.setHasStock(true);
        } else {
            skuEsModel.setHasStock(finalStockMap.get(skuInfoEntity.getSkuId()));
        }

        // TODO 热度评分(应该设计为后台可控的复杂操作)
        skuEsModel.setHotScore(0L);
        BrandEntity brandEntity = brandService.getById(skuEsModel.getBrandId());
        skuEsModel.setBrandName(brandEntity.getName());
        skuEsModel.setBrandImg(brandEntity.getLogo());
        CategoryEntity categoryEntity = categoryService.getById(skuEsModel.getCatalogId());
        skuEsModel.setCatalogName(categoryEntity.getName());

        // 设置检索属性
        skuEsModel.setAttrs(attrsList);
        return skuEsModel;
    }).collect(Collectors.toList());

    // 将数据发送给 ES保存
    R r = searchFeignService.productUp(skuEsModelList);
    if (r.getCode() == 0) {

        // 远程调用成功
        // 更新spu状态为已上架状态
        baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
    } else {
        // 远程调用失败
        // TODO 重试机制?接口幂等性?
    }

}


5.3.远程接口



5.3.1.查询sku是否有库存

WareFeignService

package com.atguigu.gmall.product.feign;

import com.atguigu.common.to.SkuHasStockTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
 * Ware 仓储服务远程接口 {@link WareFeignService}
 *
 * @author zhangwen
 * @email: 1466787185@qq.com
 */
@FeignClient("gmall-ware")
public interface WareFeignService {

    /**
     * 查询sku是否有库存
     * @param skuIds
     * @return
     */
    @PostMapping("/ware/waresku/hasstock")
    List<SkuHasStockTO> getSkuHasStock(@RequestBody List<Long> skuIds);
}

远程接口实现

WareSkuController

 /**
  * 查询sku是否有库存
  * @param skuIds
  * @return
  */
 @PostMapping("/hasstock")
 public List<SkuHasStockTO> getSkuHasStock(@RequestBody List<Long> skuIds) {
     List<SkuHasStockTO> tos = wareSkuService.getSkuHasStock(skuIds);
     return tos;
 }

WareSkuServiceImpl

/**
 * 查询sku是否有库存
 * @param skuIds
 * @return
 */
@Override
public List<SkuHasStockTO> getSkuHasStock(List<Long> skuIds) {
    List<SkuHasStockTO> tos = skuIds.stream().map(skuId -> {
        SkuHasStockTO to = new SkuHasStockTO();
        to.setSkuId(skuId);
        // 查询当前sku的库存量
        long count = baseMapper.getSkuStock(skuId);
        to.setHasStock(count > 0);
        return to;
    }).collect(Collectors.toList());
    return tos;
}

5.3.2.商品上架到ES库

SearchFeignService

package com.atguigu.gmall.product.feign;

import com.atguigu.common.to.es.SkuEsModel;
import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
 * Search 检索远程服务接口 {@link SearchFeignService}
 *
 * @author zhangwen
 * @email: 1466787185@qq.com
 */
@FeignClient("gmall-search")
public interface SearchFeignService {

    /**
     * 商品上架
     * @param skuEsModelList
     * @return
     */
    @PostMapping("/search/save/product")
    R productUp(@RequestBody List<SkuEsModel> skuEsModelList);
}

远程接口实现

ElasticSaveController

package com.atguigu.gmall.search.controller;

import com.atguigu.common.exception.BizCode;
import com.atguigu.common.to.es.SkuEsModel;
import com.atguigu.common.utils.R;
import com.atguigu.gmall.search.service.ProductServcie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;

/**
 * ElasticSearch 存储 {@link ElasticSaveController}
 *
 * @author zhangwen
 * @email: 1466787185@qq.com
 */
@Slf4j
@RequestMapping("/search/save")
@RestController
public class ElasticSaveController {

    @Autowired
    private ProductServcie productServcie;

    /**
     * 商品上架
     * @param skuEsModelList
     * @return
     */
    @PostMapping("/product")
    public R productUp(@RequestBody List<SkuEsModel> skuEsModelList) {
        boolean flag = false;
        try {
            // 返回 false,说明商品上架没有异常
            flag = productServcie.productUp(skuEsModelList);
        } catch (IOException e) {
            log.error("ElasticSaveController商品上架错误:{}", e);
            return R.error(BizCode.PRODUCT_UP_EXCEPTION.getCode(), BizCode.PRODUCT_UP_EXCEPTION.getMessage());
        }

        if (!flag) {
            return R.ok();
        } else {
            return R.error(BizCode.PRODUCT_UP_EXCEPTION.getCode(), BizCode.PRODUCT_UP_EXCEPTION.getMessage());
        }
    }
}

ProductServiceImpl

package com.atguigu.gmall.search.service.impl;

import com.atguigu.common.to.es.SkuEsModel;
import com.atguigu.gmall.search.config.ElasticSearchConfig;
import com.atguigu.gmall.search.service.ProductServcie;
import io.micrometer.core.instrument.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品服务 {@link ProductServiceImpl}
 *
 * @author zhangwen
 * @email: 1466787185@qq.com
 */
@Slf4j
@Service
public class ProductServiceImpl implements ProductServcie {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 商品上架
     * @param skuEsModelList
     */
    @Override
    public boolean productUp(List<SkuEsModel> skuEsModelList) throws IOException {
        // 给 es 中建立索引,并建立好映射关系
        // ES批量保存
        BulkRequest bulkRequest = new BulkRequest();
        skuEsModelList.forEach(skuEsModel -> {
            // 指定索引
            IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
            // 指定索引id
            indexRequest.id(skuEsModel.getSkuId().toString());
            // 转换为json
            String jsonString = JsonUtils.objectToJson(skuEsModel);
            // 设置数据
            indexRequest.source(jsonString, XContentType.JSON);
            bulkRequest.add(indexRequest);
        });

        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, ElasticSearchConfig.COMMON_OPTIONS);

        // TODO 处理批量保存错误
        // true 有错误,false 没有错误
        boolean b = bulk.hasFailures();
        // 记录日志
        List<String> collect = Arrays.stream(bulk.getItems()).map(BulkItemResponse::getId).collect(Collectors.toList());
        log.info("商品上架:{}", collect);

        return b;
    }
}


5.4.ES库查询

在Kibana中查询商品是否成功入库

在这里插入图片描述

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

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

相关文章

GEBCO海洋数据下载

一、数据集简介 GEBCO&#xff08;General Bathymetric chart of the Oceans&#xff09;旨在为世界海洋提供最权威的、可公开获取的测深数据集。 目前的网格化测深数据集&#xff0c;即GEBCO_2022网格&#xff0c;是一个全球海洋和陆地的地形模型&#xff0c;在15角秒间隔的…

GAN | 代码简单实现生成对抗网络(GAN)(PyTorch)

2014年GAN发表&#xff0c;直到最近大火的AI生成全部有GAN的踪迹&#xff0c;快来简单实现它&#xff01;&#xff01;&#xff01;GAN通过计算图和博弈论的创新组合&#xff0c;他们表明&#xff0c;如果有足够的建模能力&#xff0c;相互竞争的两个模型将能够通过普通的旧反向…

GMSL相机的相关配置(1)

文章目录一&#xff1a;GMSL相机的信息二&#xff1a;相关配置1.emmc系统下运行upgrade文件2.连接GMSL相机3.给ui可执行文件赋权限4.进入图为GMSL相机配置ui图形界面5.运行程序&#xff0c;打开摄像头一&#xff1a;GMSL相机的信息 我选择相机适配于基于Jetson AGX Orin的图为…

Docker在Windows环境的搭建和使用

文章目录安装WSL安装Docker安装Docker镜像下载Docker镜像启动gpu启动传送文件训练yolov5安装WSL Windows10和11支持Docker的安装&#xff0c;安装需要用到WSL。所以&#xff0c;我们先安装WSL。 参考文章&#xff1a;旧版 WSL 的手动安装步骤 以管理员身份打开powershell, 执行…

matplotlib综合学习

1.arange函数arange函数需要三个参数&#xff0c;分别为起始点、终止点、采样间隔。采样间隔默认值为1看例子&#xff1a; import numpy as np #import matplotlib.pyplot as plt xnp.arange(-5,5,1) print(x)2.绘制sin(x)曲线import numpy as np import matplotlib.pyplot as …

Python jieba分词如何添加自定义词和去除不需要长尾词

Python jieba分词如何添加自定义词和去除不需要长尾词 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 通过如下代码&#xff0c;读取一个txt的高频词汇&#xff1a; # 找到高频词汇t…

苹果触控笔有必要买吗?开学季性价比电容笔推荐

Apple Pencil的性能的确不错&#xff0c;但是由于它的售价实在是太高了&#xff0c;一般人还是舍不得花那么多钱买下来。目前市场上有很多平替的电容笔&#xff0c;不仅价格便宜&#xff0c;而且使用方便。那么&#xff0c;我们应该选择那个牌子的平替电笔呢&#xff1f;在购买…

“智能”创造未来:PDU智能化全面提升IDC数据中心用电能效!

一个月前&#xff0c;万众期盼的《流浪地球2》如期上映&#xff0c;无论是剧情还是特效&#xff0c;让广大观众享受到一次久违的来自中国科幻的震撼&#xff0c;时至今日仍是大家茶余饭后津津乐道的热点谈资。说起这部片子里&#xff0c;最让人紧张的部分&#xff0c;还得数为了…

解决MySQL的 Row size too large (> 8126).

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;无尽的折腾后&#xff0c;终于又回到…

电脑系统崩溃怎么修复教程

系统崩溃了怎么办? 如今的软件是越来越复杂、越来越庞大。由系统本身造成的崩溃即使是最简单的操作&#xff0c;比如关闭系统或者是对BIOS进行升级都可能会对PC合操作系统造成一定的影响。下面一起来看看电脑系统崩溃修复方法步骤。 工具/原料&#xff1a; 系统版本&#xf…

LeetCode-47. 全排列 II

目录题目思路回溯法拓展题目来源 47. 全排列 II 题目思路 这道题目和46.全排列的区别在与给定一个可包含重复数字的序列&#xff0c;要返回所有不重复的全排列。 强调的是去重一定要对元素进行排序&#xff0c;这样我们才方便通过相邻的节点来判断是否重复使用了。 我以示例中…

CC2530+ESP8266使用MQTT协议上传阿里云的问题

ATMQTTPUB<LinkID>,<"topic">,<"data">,<qos>,<retain>LinkID: 当前只支持 0 topic: 发布主题, 最长 64 字节 data: 发布消息, data 不能包含 \0, 请确保整条 ATMQTTPUB 不超过 AT 指令的最大长度限制 qos: 发布服务质量, 参…

项目管理软件排行榜!盘点前十名!

项目管理软件排行榜&#xff01;盘点前十名&#xff01; 如今企业规模不断扩大&#xff0c;业务逐渐复杂化&#xff0c;项目管理已经成为现代企业管理中不可或缺的一环。作为协调管理者、团队成员和客户之间交流的工具&#xff0c;项目管理软件不仅可以提高工作效率&#xff0…

数据结构入门--时间 空间复杂度

数据结构入门 时间 空间复杂度解析 目录 一. 算法效率 二. 时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3 题目练习 题目一 题目二 题目三 题目四 题目五 题目六 题目七 三. 空间复杂度 3.1 题目练习 题目一 题目二 题目三 一. 算法效率 算法效率…

Vim常用命令汇总

目录1 普通模式2 插入模式3 可视模式4 命令行模式4 文件操作5 动作命令1 普通模式 命令操作符合命令作用等同命令.重复上次修改x删除光标下的字符dd删除整行>G从当前行到文档末尾处的缩进层级a在当前光标之后添加内容i在当前光标之前添加内容A在当前行的结尾添加内容$aI在当…

Docker之安装redis

下面记录一下在docker中安装redis过程 1.查看redis镜像 docker search redis2.拉去镜像到Linux //指定拉取redis版本 docker pull redis:6.0 //不指定版本默认拉取最新 docker pull redis3.查看镜像是否拉取成功 docker images4.启动redis //2f66aad5324为redis的image id do…

驾驭云安全:2023年云安全展望

由于其的良好的可扩展性和优质的事件处理效率&#xff0c;云技术已成为现代企业的必备的管理技术之一&#xff0c;目前他已经成为所有行业及企业的热门选择。然而&#xff0c;攻击面积的增加以及不针对云技术衍生出来的多类攻击方式&#xff0c;使许多企业更容易受到威胁和数据…

Docker学习总结

1、镜像操作 1.1 拉取、查看镜像 步骤一&#xff1a; 首先去镜像仓库搜索nginx镜像&#xff0c;比如[DockerHub]( Docker Hub Container Image Library | App Containerization ) : 步骤二&#xff1a; 根据查看到的镜像名称&#xff0c;拉取自己需要的镜像 通过命令&…

代码随想录 NO54 |单调栈_leetcode 503.下一个更大元素II 42. 接雨水

单调栈_leetcode 503.下一个更大元素II 42. 接雨水单调栈第二天&#xff0c;也是本轮刷题任务倒数第二天&#xff0c;加油&#xff01; 503.下一个更大元素II 这道题和739. 每日温度几乎如出一辙。在遍历的过程中模拟走了两遍nums。 class Solution:def nextGreaterElements(…

算法设计与分析——十大经典排序算法一(1--5)

目录 算法设计与分析——十大经典排序算法 第1关&#xff1a;冒泡排序 参考代码 第2关&#xff1a;选择排序 参考代码 第3关&#xff1a;插入排序 参考代码 第4关&#xff1a;希尔排序 参考代码 第5关&#xff1a;归并排序 参考代码 作者有言 一个不知名大学生&#x…