IK分词器热刷新词库实践分享

news2024/10/7 12:28:05

目录

前言

什么是分词器?

ik分词器简介

ik分词器和默认分词器的对比

ik分词器介绍

ik分词器的分词问题

自定义词库

主配置解说

通过配置文件自定义词库

Step1: 新建自定义分词库

Step2: 将我们的自定义词添加到ik的配置文件中

Step3: 重启es,查看分词

配置化方式自定义词库存在的问题

热更新词库方案

ik分词器热更新词库实践

IK分词器源码下载

导入maven工程

源码中词典加载大体流程

修改源码

修调整elasticsearch.version

在pom文件中添加mysql驱动器依赖

创建数据库配置文件jdbc-reload.properties,放在IK项目的config文件夹下

新增HotDictReloadThread类

修改org.wltea.analyzer.dic.Dictionary#loadMainDict方法

修改org.wltea.analyzer.dic.Dictionary#loadStopWordDict方法

org.wltea.analyzer.dic.Dictionary#initial调用HotDictReloadThread方法

修改插件的权限

建立数据库表

打包

加入依赖

package

安装

测试验证

关键词验证

1. “水平思维”关键词验证

2. 网络流行语“他是显眼包”验证

3. 网络流行语“香菇蓝瘦”验证

停用词验证

1. “我是熊二呢”短语验证

2. “一个老流氓”短语验证

总结


前言

本篇文章介绍了ElasticSearch分词器相关内容,介绍了什么是分词器,什么是ik分词器,ik分词器目前存在的问题以及如何通过修改ik分词器的源码来实现热更新词库。

什么是分词器?

Elasticsearch是基于倒排索引来实现搜索功能,而倒排索引的基础就是分词。Elasticsearch默认的分词器支持英文的分词,因为分词很简单,基本基于空格就可以分出来,而汉语的分词则困难很多。分词是把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个 匹配操作。

ik分词器简介

ik分词器和默认分词器的对比

默认的中文分词器是将每个字看成一个词,比如"中国人很喜欢吃油条",会被分为“中 国 人 很 喜 欢 吃 油 条”这几个字,而采用IK分词器 可以分为“中国人 很 喜欢 吃 油条”,看下上面分词后的结果,肯定是 ik 的分词结果比较符合中文。

以“中国人很喜欢吃油条”这个句话为例,标准分词器会将这句话分为:“中”  “国”  “人”  “很”  “喜” “欢” “吃”  “油”  “条”,例如:

image.png

可以看出来,很不符合中文词的表述习惯,因为这段话不仅仅可以分为这10个字,还可以组成如:“中国”,“中国人”,“喜欢”等等。

我们来看看ik分词器的分词效果,以ik分词器的ik_max_word为例,“中国人很喜欢吃油条”这句话就可以拆成很多种,如:“中国人”,“中国”,“国人”,“很喜欢”等,例如:

image.png

从上面分词后的结果可以看出,肯定是ik分词结果比较符合中文习惯

ik分词器介绍

在搜索引擎领域,比较成熟和流行的中文分词器,就是ik分词器,它提供了2种分词的模式,分别为ik_max_word和ik_smart

  • ik_max_word:将需要分词的文本做最小粒度的拆分,尽量分更多的词

  • ik_smart:将需要分词的文本做最大粒度的拆分

ik_max_word 的分词效果

语句

POST _analyze
{
  "text": ["中国人很喜欢吃油条"], 
  "analyzer": "ik_max_word"
}

结果

{
  "tokens" : [
    {
      "token" : "中国人",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "中国",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "国人",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "很喜欢",
      "start_offset" : 3,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "喜欢吃",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "喜欢",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "吃油",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "油条",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 7
    }
  ]
}

ik_smart的分词效果

语句

POST _analyze
{
  "text": ["中国人很喜欢吃油条"], 
  "analyzer": "ik_smart"
}

结果

{
  "tokens" : [
    {
      "token" : "中国人",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "很喜欢",
      "start_offset" : 3,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "吃",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "CN_CHAR",
      "position" : 2
    },
    {
      "token" : "油条",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 3
    }
  ]
}

ik分词器的分词问题

虽然通过ik_smart和ik_max_word可以做到中文分词效果,但是如果对于一些网络流行语或者我们公司内部的一些自定义的短语,无法做到分词的效果,如网络流行语:“香菇蓝瘦”,我们期望的是“香菇蓝瘦”也是其中的一个词,然后并没有

image.png

如公司的一些短语,如“星云思维”、“水平思维”,我们期望它成为一个完整的词,然后确没有

image.png

image.png

那么如何去按照我们定义的词去进行分词自适应呢?

自定义词库

主配置解说

ik配置文件地址:/usr/share/elasticsearch/plugins/ik/config 目录下都是存放配置文件

image.png

下面是这些主要配置文件含义:

  • IKAnalyzer.cfg.xml:用来配置自定义词库

  • main.dic:原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起,每个单词占据一行

  • quantifier.dic:放了一些单位相关的词

  • suffix.dic:放了一些后缀

  • surname.dic:中国的姓氏

  • stopword.dic:英文停用词

  • preposition.dic:介词词典

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>
        <!--用户可以在这里配置远程扩展字典 -->
        <!-- <entry key="remote_ext_dict">words_location</entry> -->
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

ik原生最重要的两个配置文件

  • main.dic:包含了原生的中文词语,会按照这个里面的词语去分词

  • stopword.dic:包含了英文的停用词。custom/ext_stopword.dic 中包含了中文的一些扩展词

什么是停用词?与其他词相比,功能词没有什么实际含义,比如'the'、'is'、'at'、'which'、'on'等。

通过配置文件自定义词库

通过配置化的方式新增词库主要分为3步,分别为:

1. 新建自定义分词库

2. 添加到ik的配置文件中

3. 重启es,查看分词

下面介绍一下这3步的具体配置

Step1: 新建自定义分词库

我们在/usr/share/elasticsearch/plugins/ik/config目录下新建一个文件夹custom,然后建一个dic文件(zj.dic),如:

image.png

把这些热门词放到该文件中,如:

image.png

Step2: 将我们的自定义词添加到ik的配置文件中

image.png

Step3: 重启es,查看分词

重启es,然后在kibana上查看分词

image.png

image.png

这样我们通过配置化的方式实现了分词效果

配置化方式自定义词库存在的问题

我们使用配置化的方式自定义词库的时候,每次都得重启,而且得逐个节点依次修改,是不是有点不方便呢?这种方式的主要缺点有:

  • 每次添加完词库,都要重启es才能生效,非常麻烦

  • es是分布式的,生产环境一般几十个个es节点,每次添加完词库,然后重启节点,可想而知......

热更新词库方案

目前ik分词器热更新词库的方案有两种

  • 修改ik分词器源码,后台启动一个线程,每隔一段时间从MySQL数据库中,抽取数据,进行自动加载词库

  • 基于ik分词器原生的热更新方案,部署一个web服务器,提供一个http接口,通过modified和tag两个http响应头,来提供词语的热更新

推荐第一种方案修改ik分词器源码, 第二种方案ik git社区官方都不建议采用,不太稳定。下面也是围绕着第一种方案进行源码改造来实现热更新词库

ik分词器热更新词库实践

IK分词器源码下载

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

我选择的版本是7.9.3的版本,选中图中的Source code(zip)进行下载

image.png

导入maven工程

image.png

源码中词典加载大体流程

ik分词器实现了ES的AnalysisPlugin接口,通过工厂方法初始化词典,加载默认配置

image.png

image.png

image.png

默认会根据DefaultConfiguration找到主词典和中文量词词典路径,同时DefaultConfiguration会根据classpath下配置文件IKAnalyzer.cfg.xml,找到扩展词典和停止词典路径,用户可以在该配置文件中配置自己的扩展词典和停止词典。找到个词典路径后,初始化Dictionary.java,Dictionary是单例的。在Dictionary的构造函数中加载词典。Dictionary是IK的词典管理类,真正的词典数据是存放在DictSegment中,该类实现了一种树结构,如下图。

image.png

举个例子,要对字符串“A股市场”进行分词,首先拿到字符串的第一个字符'A',在上面的tree中可以匹配到A节点,然后拿到字符串第二个字符'股',首先从前一个节点A往下找,我们找到了股节点,股是一个终点节点。所以,“A股“是一个词。

Dictionary加载主词典,以,将主词典保存到它的_MainDict字段中,加载完主词典后,立即加载扩展词典,扩展词典同样保存在_MainDict中。

image.png

fillSegment方法是DictSegment加载单个词的核心方法,charArray是词的字符数组,先是从存储节点搜索词的第一个字符开始,如果不存在则创建一个节点用于存储第一个字符,后面递归存储,直到最后一个字符。

image.png

image.png

因此,我们只需要在加载加载主词典及扩展词典的时候,通过fillSegment方法填充词典即可,下面介绍具体的源码修改流程。

修改源码

简单说下整体思路: 开启一个后台线程,扫描mysql中定义的表,加载数据。

修调整elasticsearch.version

本次下载的是7.9.3版本,但是下载下来后是7.4.0版本,因为我用的是7.9.3版本的ES这里需要改一下版本

image.png

修改为:

image.png

在pom文件中添加mysql驱动器依赖

<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

创建数据库配置文件jdbc-reload.properties,放在IK项目的config文件夹下

jdbc.url=jdbc:mysql://10.xxx.xxx.XX:3306/canal-test?serverTimezone=UTC
jdbc.user=ueranme
jdbc.password=password
jdbc.reload.extend.sql=select word from es_extra_main
jdbc.reload.stop.sql=select word from es_extra_stopword
# 间隔时间 毫秒
jdbc.reload.interval=10000

reload间隔,1秒钟轮训一次

新增HotDictReloadThread类

在org.wltea.analyzer.dic目录下,新增一个HotDictReloadThread类,死循环去调用Dictionary.getSingleton().reLoadMainDict(),重新加载词典,HotDictReloadThread结构如下:

package org.wltea.analyzer.dic;

import org.wltea.analyzer.help.ESPluginLoggerFactory;


/**
 * @author 
 * @version 1.0
 * @date 2024/1/12 下午7:21
 * <p>Copyright: Copyright (c) 2024<p>
 */
public class HotDictReloadThread implements Runnable {

    private static final org.apache.logging.log4j.Logger logger = ESPluginLoggerFactory.getLogger(HotDictReloadThread.class.getName());

    @Override
    public void run() {
        while (true) {
            logger.info("[======HotDictReloadThread======] begin to reload hot dict from dataBase......");
            Dictionary.getSingleton().reLoadMainDict();
        }
    }
}

看下reLoadMainDict这个方法的执行逻辑

image.png

reLoadMainDict方法的核心逻辑有两块:

  • tmpDict.loadMainDict():加载主词库

  • tmpDict.loadStopWordDict():加载停用词词库

由此可以看出,只要我们把读取数据库的逻辑放到这两个方法里面就可以了,下面我们分别来修改这两个方法。

修改org.wltea.analyzer.dic.Dictionary#loadMainDict方法

通过修改loadMainDict来读取MySQL中的主词库,来实现热加载,修改的点如下:

增加this.loadMySQLExtDict(),该方法就是将MySQL表中的数据加载到词库中

image.png

loadMySQLExtDict()方法的主体逻辑是通过JDBC查询MySQL

代码如下:

private static Properties prop = new Properties();

static {
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        logger.error("error", e);
    }
}

/**
 * 从mysql加载热更新词典
 */
private void loadMySQLExtDict() {
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
        Path file = PathUtils.get(getDictRoot(), "jdbc-reload.properties");
        prop.load(new FileInputStream(file.toFile()));

        logger.info("[==========]jdbc-reload.properties");
        for(Object key : prop.keySet()) {
            logger.info("[==========]" + key + "=" + prop.getProperty(String.valueOf(key)));
        }

        logger.info("[==========]query hot dict from mysql, " + prop.getProperty("jdbc.reload.extend.sql") + "......");

        conn = DriverManager.getConnection(
                prop.getProperty("jdbc.url"),
                prop.getProperty("jdbc.user"),
                prop.getProperty("jdbc.password"));
        stmt = conn.createStatement();
        rs = stmt.executeQuery(prop.getProperty("jdbc.reload.extend.sql"));

        while(rs.next()) {
            String theWord = rs.getString("word");
            logger.info("[==========]hot word from mysql: " + theWord);
            _MainDict.fillSegment(theWord.trim().toCharArray());
        }

        Thread.sleep(Integer.valueOf(String.valueOf(prop.get("jdbc.reload.interval"))));
    } catch (Exception e) {
        logger.error("erorr", e);
    } finally {
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
        if(stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
    }
}

修改org.wltea.analyzer.dic.Dictionary#loadStopWordDict方法

在loadStopWordDict方法中增加loadMySQLStopWordDict,该方法实现从MySQL中加载停用词到词典中

image.png

loadMySQLStopWordDict实现代码为:

/**
 * 从mysql加载停用词
 */
private void loadMySQLStopWordDict() {
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
        Path file = PathUtils.get(getDictRoot(), "jdbc-reload.properties");
        prop.load(new FileInputStream(file.toFile()));

        logger.info("[====loadMySQLStopWordDict======] jdbc-reload.properties");
        for(Object key : prop.keySet()) {
            logger.info("[==========]" + key + "=" + prop.getProperty(String.valueOf(key)));
        }

        logger.info("[==========]query hot stop word dict from mysql, " + prop.getProperty("jdbc.reload.stop.sql") + "......");

        conn = DriverManager.getConnection(
                prop.getProperty("jdbc.url"),
                prop.getProperty("jdbc.user"),
                prop.getProperty("jdbc.password"));
        stmt = conn.createStatement();
        rs = stmt.executeQuery(prop.getProperty("jdbc.reload.stop.sql"));

        while(rs.next()) {
            String theWord = rs.getString("word");
            logger.info("[==========]hot stop word from mysql: " + theWord);
            _StopWords.fillSegment(theWord.trim().toCharArray());
        }

        Thread.sleep(Integer.valueOf(String.valueOf(prop.get("jdbc.reload.interval"))));
    } catch (Exception e) {
        logger.error("error", e);
    } finally {
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
        if(stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
    }
}

org.wltea.analyzer.dic.Dictionary#initial调用HotDictReloadThread方法

image.png

修改插件的权限

image.png

grant {
  // needed because of the hot reload functionality
  permission java.net.SocketPermission "*", "connect,resolve";
  permission java.lang.RuntimePermission "setContextClassLoader";
};

如何还不行的话,切换到/usr/share/elasticsearch/jdk/conf/security目录下,在java.policy文件最后一行加上

permission java.lang.RuntimePermission "setContextClassLoader";

如果还有java.net.SocketPermission的报错,则在java.policy文件的后面再加上

permission java.net.SocketPermission "*", "connect,resolve";

image.png

建立数据库表

CREATE TABLE `es_extra_main`
(
    `id`          int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `word`        varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '词',
    `is_deleted`  tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
    `update_time` timestamp(6)                       NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP (6) COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `es_extra_stopword`
(
    `id`          int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `word`        varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '词',
    `is_deleted`  tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
    `update_time` timestamp(6)                       NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP (6) COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

打包

加入依赖

将MySQL的jar包依赖加入进来,否则打包会缺少jar包保持错。

image.png

<include>mysql:mysql-connector-java</include>

package

打包成zip文件,然后加压成文件夹

image.png

安装

将elasticsearch-analysis-ik-7.9.3.zip文件拷贝到/usr/share/elasticsearch/plugins/ik目录下:

cp elasticsearch-analysis-ik-7.9.3.zip /usr/share/elasticsearch/plugins/ik/

解压

unzip elasticsearch-analysis-ik-7.9.3.zip

image.png

然后重启es和kibana,可以看到es已经开始加载词库了

image.png

测试验证

在数据库表中中新增下面自己的想要的关键词,然后去Kibana中做测试验证

关键词验证

1. “水平思维”关键词验证

未在数据中插入词库验证

image.png

在数据中插入词库验证,插入“水平思维”

image.png

image.png

分词的效果

image.png

2. 网络流行语“他是显眼包”验证

在数据中插入网络流行语“显眼包”验证,插入“他是显眼包”

插入之前

image.png

数据库中增加“显眼包”,验证

image.png

image.png

3. 网络流行语“香菇蓝瘦”验证

image.png

image.png

image.png

停用词验证

停用词指的是有些词是关键词,但是出于某些业务场景,不想使用这些关键词被检索到,可以将这些词语放到停用词典

1. “我是熊二呢”短语验证

验证前,测试短语“我是熊二呢”

image.png

我们将“呢”、“二”放到停用词中

image.png

在kibana上验证,发现“呢”、“二”已经没了

image.png

2. “一个老流氓”短语验证

验证前,测试短语“一个老流氓”,分词后的效果为:

image.png

我们发现“流氓”也在其中,对于这种污秽的言辞,我们希望屏蔽它,营造一个良好的网络环境,我们将“流氓”加到停用词库中,再进行测试

image.png

我们再次运行,发现“流氓”已经没了,达到了我们验证的效果

image.png

总结

本文主要讲解了什么是ik分词器,如何通过配置化的方式实现自定义词库,配置化方式存在的一些问题,以及如何通过修改ik分词器源码来实现扩展词库以及停用词库热刷新,该实践证明了通过该方案实现的可行性,后续有项目需要基于es分词器实现热刷新,可以借鉴。

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

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

相关文章

DSP C6000教学实验箱操作教程_数字图像处理:5-3 图像缩放

一、实验目的 学习图像缩放的原理&#xff0c;掌握图像的读取方法&#xff0c;并实现图像缩放。 二、实验原理 图像缩放 在计算机图像处理和计算机图形学中&#xff0c;图像缩放是指对数字图像的大小进行调整的过程。图像缩放是一种非平滑的过程&#xff0c;需要在处理效率以…

通过“BOSS”精通比特币,深入认识私钥、账户和钱包

来源:币界原创 作者:636Marx 无论当今数字货币技术如何发展&#xff0c;认识区块链技术幕后的关键机制至关重要。无论您是新手还是经验丰富的数字货币从业者&#xff0c;掌握钱包地址、公钥和私钥的复杂性都有无可替代重要性。进入 BOSS Wallet&#xff0c;这是一款尖端的 Web…

Kubernates容器化JVM调优笔记(内存篇)

Kubernates容器化JVM调优笔记&#xff08;内存篇&#xff09; 先说结论背景思路方案 先说结论 1、首先如果是JDK8&#xff0c;需要使用JDK8_191版本以上&#xff0c;才支持容器化环境和以下参数&#xff0c;否则就更新到JDK10以上&#xff0c;选择对应的镜像构建就行了 2、在容…

day01-anaconda的安装

Anaconda的安装 参考地址&#xff1a; http://t.csdnimg.cn/mUmSp 安装完毕&#xff0c;可以卸载电脑中的其他python版本&#xff0c;在控制面板中进行卸载。 在命令行指令中输入 pythonPython 3.8.3 (default, Jul 2 2020, 17:30:36) [MSC v.1916 64 bit (AMD64)] :: An…

【React 】折叠面板,点击展开时再请求数据

需求背景&#xff1a;使用折叠面板的形式展示数据&#xff0c;面板内部数据需要在打开时请求接口获取。 遇到问题&#xff1a;最开始使用Antd 的折叠面板组件&#xff0c;它对于数据直接渲染是没问题的&#xff0c;但是不好满足打开面板时再动态加载数据的需求&#xff0c;于是…

兴业严选|朝阳、大兴、丰台、等5.9折起总有一套适合你~

近日于上海&#xff0c;出现了一桩令人始料未及之事。一套地处浦东、面积达 245.7 平方米的住宅进行挂网拍卖。 出乎意料的是&#xff0c;此套房子受到众多买家的青睐&#xff0c;历经一番激烈的竞价竞争&#xff0c;最终以 1766 万元的价格成交&#xff0c;折合每平方米 7187…

kakfa发版丢消息事件分析

背景 其他部门同事反馈在项目发版/重启(kill -15)的那段时间&#xff0c;经常会出现导致 C 端业务出现问题&#xff0c;从而产生资损 一听资损&#xff0c;赶紧应答下来&#xff0c;了解了下具体情况&#xff0c;然后立马去排查了 问题分析 结合同事的描述以及对业务的了解&a…

8小时出500杯,投诉三次辞退?Manner逼疯员工…?

一边歇斯底里的咆哮&#xff1a;「你投诉啊」&#xff01;一边将咖啡粉泼向顾客……一场大战要不是隔着岛台&#xff0c;就真的燃起来了……‍ 好巧不巧&#xff0c;同一天&#xff0c;另一段视频中的顾客就没那么好运了&#xff0c;男店员冲上去就给女顾客一个耳光……‍‍ 想…

【ai】tx2-nx 开通samba

ubutn服务器加入了samba给jetson也加入一个samba 添加root用户 密码与nvidia一样 添加nvidia 到suoders中并添加samba账号 nvidia@tx2-nx:~$ nvidia@tx2-nx:~$ nvidia@tx2-nx:~$ nvidia@tx2-nx:~$ sudo vi /etc/sudoers nvidia@tx2-nx:~$ sudo chm

成熟的自动化运维平台有哪些特点?

点击进入运维资料库 在现代企业运维中&#xff0c;自动化运维平台已经成为不可或缺的工具。随着技术的发展&#xff0c;企业对系统稳定性和效率的要求越来越高&#xff0c;传统的手工运维方式已无法满足需求。于是&#xff0c;自动化运维平台应运而生&#xff0c;成为提升运维效…

泵设备的监测控制和智慧运维

泵是一种输送流体或使流体增压的机械。它通过各种工作原理&#xff08;如离心、柱塞等&#xff09;将机械能转换为流体的动能或压力能&#xff0c;从而实现液体的输送、提升、循环等操作。 泵的一些具体应用场景&#xff1a; 1.智能水务&#xff1a;在城市供水管网中&#xff…

推动产业数字化转型,六个方面引领变革

从工业经济时代走向数字经济时代&#xff0c;世界经济发生着全方位、革命性的变化&#xff0c;产业数字化便是最显著的表现之一。当前&#xff0c;产业数字化不断深入发展&#xff0c;平台经济、工业互联网、智能制造等新业态、新模式不断涌现&#xff0c;成为了数字经济的重要…

【element-ui】el-date-picker动态设置picker-options

<el-date-pickerv-model"formObj.startDate"type"date"placeholder"开始时间":picker-options"startPickerOptions"> </el-date-picker><el-date-pickerv-model"formObj.endDate"type"date"placeh…

【linux】内核源码TCP->IP->L2层函数调用继续摸索中

日志打印的时候&#xff0c;把行数也打印了&#xff1a; 登录 - Gitee.comhttps://gitee.com/r77683962/linux-6.9.0/commit/b847489a9910f68b9581fd8788807c697c82cdbd 上回基于应用层wget操作找到TCP调用的一些接口&#xff0c;并且已经到IP层的一些接口&#xff0c;当前基…

vue2与vue3数据响应式对比之检测变化

vue2 由于javascript限制&#xff0c;vue不能检测数组和对象的变化 什么意思呢&#xff0c;举例子来说吧 深入响应式原理 对象 比如说我们在data里面定义了一个info的对象 <template><div id"app"><div>姓名: {{ info.name }}</div><…

WPF文本框中加提示语

效果&#xff1a; WPF中貌似不能像winfrom里一样直接加提示语&#xff0c;需要使用TextBox.Style&#xff0c;将Trigger标签插入进去。 贴源码&#xff1a; <WrapPanel Name"TakeOverExpressNo1"><Label Content"物流单号&#xff1a;"><…

人工智能在气象预报领域的崛起:GraphCast引领新纪元

最近&#xff0c;谷歌推出的天气预测大模型GraphCast在全球范围内引起了广泛关注&#xff0c;其卓越的表现不仅刷新了人们对AI能力的认知&#xff0c;更预示着传统天气预报工作模式的深刻变革。 GraphCast是一款基于机器学习技术的天气预测工具&#xff0c;它通过深度学习和大数…

安卓开发使用proxyman监控真机

1、真机跟电脑连接到同个网络中 2、手机里面设置代理&#xff0c;代理地址为proxyman上面指示的地址。 3、一般情况下&#xff0c;电脑的对应的端口是没开放的。需要到防火墙里面新建规则。入站规则 选择端口输入上方端口号 这样就能监控到了

QT自定义标题栏窗口其一:实现拖动及可拉伸效果

1、效果 2、核心代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(paren

js处理数据(过滤)

复选框的值这里为true或false 选中为true&#xff0c;未选中为false 看看数据&#xff1a; type中的前面那些字母是固定的不会变 括号里面的不固定&#xff0c;那就把固定的作为前缀去过滤&#xff0c;后面怎么变都无所谓&#xff0c;当checkbox三个值中的某个或某些值为false时…