ElasticSearch的自动补全功能(拼音分词器、自定义分词器、DSL实现自动补全查询、RestAPI实现自动补全查询)

news2024/12/19 2:47:26

文章目录

  • 1. 什么是自动补全
  • 2. 拼音分词器
    • 2.1 初识拼音分词器
    • 2.2 下载拼音分词器
    • 2.3 安装拼音分词器
    • 2.4 测试拼音分词器
  • 3. 自定义分词器
    • 3.1 拼音分词器存在的问题
    • 3.2 分词器(analyzer)的组成
    • 3.3 如何自定义分词器
    • 3.4 拼音分词器的可选参数
    • 3.5 配置自定义分词器的tokenizer和filter
    • 3.6 如何使用自定义分词器
    • 3.7 测试自定义分词器
      • 3.7.1 直接测试
      • 3.7.2 插入文档测试
    • 3.8 使用自定义分词器要注意的事项
  • 4. DSL实现自动补全查询
    • 4.1 字段的类型的约束
    • 4.2 查询语法
  • 5. 自动补全案例
    • 5.1 准备工作
      • 5.1.1 创建hotel索引库
      • 5.1.2 导入测试工程
      • 5.1.3 导入酒店数据到数据库中
      • 5.1.4 将数据库中的数据导入到ElasticSearch
    • 5.2 测试自动补全功能
  • 6. RestAPI实现自动补全查询
  • 7. 综合案例:实现搜索框自动补全

视频教程:SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务


阅读本文前可以先阅读以下文章:

  • ElasticSearch快速入门——上篇(认识ElasticSearch、安装ElasticSearch、安装kibana、IK分词器、ElasticSearch中的基本概念、索引库操作、文档操作)
  • ElasticSearch快速入门——下篇(在Java代码中操作ElasticSearch、JavaRestClient、操作索引库、操作文档、DSL查询、JavaRestClient查询、数据聚合)
  • 通过docker启动ElasticSearch后为ElasticSearch设置用户和密码

1. 什么是自动补全

ElasticSearch 中的自动补全跟我们理解的自动补全不太一样,为了大家理解,我们来看一个案例

在这里插入图片描述

当我们在搜索框输入 sj 时,搜索框下方会显示以 sj 拼音首字母开头的词条(如手机、湿巾、数据线、史记、书架等),这个功能被称为自动补全

自动补全功能可以让用户尽可能地搜索到想要的东西,而不需要打出完整的内容

2. 拼音分词器

要想实现自动补全功能,我们需要先学习一下拼音分词器,因为自动补全功能是基于拼音分词器实现的

2.1 初识拼音分词器

拼音分词器的官网:analysis-pinyin

拼音分词器跟我们学过的 IK 分词器相似,都是 ElasticSearch 的一个插件

2.2 下载拼音分词器

下载地址:v7.17.18

在这里插入图片描述


本次演示使用的 ElasticSearch 版本为 7.17.18

其它 ElasticSearch 版本对应的拼音分词器的下载地址:Tags

2.3 安装拼音分词器

解压完成之后,将拼音分词器上传到 ElasticSearch 的 plugin 目录下(本次演示是通过 docker 安装 ElasticSearch 的)


先将拼音分词器上传到服务器,一般是当前用户的目录

cd ~

接着将拼音分词器复制到 ElasticSearch 的 plugin 的目录下

sudo cp elasticsearch-analysis-pinyin-7.17.18 -r /var/lib/docker/volumes/elasticsearch-plugins/_data

最后重启 ElasticSearch 容器

sudo docker restart elasticsearch

2.4 测试拼音分词器

我们在 Kibana 提供的控制台中测试拼音分词器是否生效


在浏览器打开 Kibana 提供的控制台

http://127.0.0.1:5601/app/dev_tools#/console

输入以下内容测试拼音分词器是否生效

POST /_analyze
{
  "text": [
    "练习时长两年半"
  ],
  "analyzer": "pinyin"
}

测试结果如下,主要包含两部分内容:

  1. 每个字的完整拼音
  2. 每个字的拼音首字母的合并

在这里插入图片描述

{
  "tokens" : [
    {
      "token" : "lian",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "lxsclnb",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "xi",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "shi",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "chang",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "liang",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "nian",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "ban",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 6
    }
  ]
}

3. 自定义分词器

3.1 拼音分词器存在的问题

拼音分词器还无法正常用于生产环境,因为拼音分词器存在一些问题

以 “练习时长两年半” 这句话为例,拼音分词器存在以下问题:

  1. “练习时长两年半” 这句话没有被分词,而是作为一个整体出现
  2. 把 “练习时长两年半” 这句话中的每一个字都形成了一个拼音(用处不大)
  3. 分词后的结果只剩下拼音,没有汉字

其实我们很少使用拼音搜索,大多数情况下我们都是使用中文去搜索的,分词后有拼音只是锦上添花,分词后的结果中汉字是必须保留的,所以我们需要对拼音分词器做一些配置,也就是自定义分词器

3.2 分词器(analyzer)的组成

ElasticSearch 中分词器(analyzer)的组成有三部分:

  • character filters:在 tokenizer 之前对文本进行处理,例如删除字符、替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term),例如 keyword(不分词)、ik_smart 等
  • tokenizer filter:将 tokenizer 输出的词条做进一步处理,例如大小写转换、同义词处理、拼音处理等

在这里插入图片描述

3.3 如何自定义分词器

要想自定义分词器,一定要在创建索引库的时候去设置

我们可以在创建索引库时,通过 settings 来配置自定义的 analyzer(分词器)

自定义分词器时可以只设置分词器(analyzer)的某个部分

在这里插入图片描述

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "pinyin"
        }
      }
    }
  }
}

tokenizer 我们使用 ik_max_word,先分词,分好词后再将词条交给拼音分词器处理,这样做可以解决拼音分词器没有分词的问题

但是拼音分词器还存在两个问题:分词后的每一个字都形成了一个拼音、分词后的结果只剩下拼音,没有汉字

3.4 拼音分词器的可选参数

我们需要对拼音分词器做进一步的定制

在拼音分词器的官网上,给出了很多的可选参数(Optional Parameters)

在这里插入图片描述

参数名称含义
keep_first_letter启用后,只保留每个汉字的第一个字母。例如,刘德华变为ldh。默认:true。
keep_separate_first_letter启用后,保留每个汉字的第一个字母,并分别显示。例如,刘德华变为l,d,h。默认:false。注意:这可能会因词频增加查询的模糊度。
limit_first_letter_length设置第一个字母结果的最大长度。默认:16。
keep_full_pinyin启用后,保留每个汉字的完整拼音。例如,刘德华变为[liu,de,hua]。默认:true。
keep_joined_full_pinyin启用后,将每个汉字的完整拼音连接起来。例如,刘德华变为[liudehua]。默认:false。
keep_none_chinese保留结果中的非汉字字母或数字。默认:true。
keep_none_chinese_together保留非汉字字母在一起。默认:true。例如,DJ音乐家变为DJ,yin,yue,jia。当设置为false时,DJ音乐家变为D,J,yin,yue,jia。注意:需要先启用keep_none_chinese。
keep_none_chinese_in_first_letter在首字母中保留非汉字字母。例如,刘德华AT2016变为ldhat2016。默认:true。
keep_none_chinese_in_joined_full_pinyin在连接的完整拼音中保留非汉字字母。例如,刘德华2016变为liudehua2016。默认:false。
none_chinese_pinyin_tokenize如果非汉字字母是拼音,将其拆分为单独的拼音词。默认:true。例如,liudehuaalibaba13zhuanghan变为liu,de,hua,a,li,ba,ba,13,zhuang,han。注意:需要先启用keep_none_chinese和keep_none_chinese_together。
keep_original启用后,保留原始输入。默认:false。
lowercase将非汉字字母转换为小写。默认:true。
trim_whitespace默认:true。
remove_duplicated_term启用后,移除重复的词以节省索引空间。例如,de的变为de。默认:false。注意:可能与位置相关的查询受到影响。
ignore_pinyin_offset在6.0版本之后,偏移量受到严格限制,不允许重叠的词。通过此参数,将允许重叠的词,忽略偏移量。请注意,所有与位置相关的查询或高亮将变得不正确。如果需要偏移量,请设置为false。默认:true。

3.5 配置自定义分词器的tokenizer和filter

在这里插入图片描述

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  }
}

创建一个自定义的分词器my_analyzer,使用ik_max_word分词器进行中文分词,并通过pinyin过滤器将中文词条转换为拼音,保留了原始中文词条和连接起来的全拼,同时限制了首字母长度并移除重复的词条

3.6 如何使用自定义分词器

自定义分词器创建好了之后,该怎么使用呢

要使用自定义分词器,我们需要在定义索引库字段(Mapping)的时候使用

在这里插入图片描述

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_analyzer"
      }
    }
  }
}

3.7 测试自定义分词器

3.7.1 直接测试

POST /test/_analyze
{
  "text": [
    "练习时长两年半"
  ],
  "analyzer": "my_analyzer"
}

测试结果

在这里插入图片描述

{
  "tokens" : [
    {
      "token" : "练习",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "lianxi",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "lx",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "时长",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "shichang",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "sc",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "两年",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "liangnian",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "ln",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "两",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "COUNT",
      "position" : 3
    },
    {
      "token" : "liang",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "COUNT",
      "position" : 3
    },
    {
      "token" : "l",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "COUNT",
      "position" : 3
    },
    {
      "token" : "年半",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "nianban",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "nb",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    }
  ]
}

3.7.2 插入文档测试

测试数据如下(狮子和虱子的拼音是一样的

POST /test/_doc/1
{
  "id": 1,
  "name": "狮子"
}
POST /test/_doc/2
{
  "id": 2,
  "name": "虱子"
}

我们先通过拼音 shizi 来搜索

GET /test/_search
{
  "query": {
    "match": {
      "name": "shizi"
    }
  }
}

成功搜索出狮子和虱子

在这里插入图片描述

但如果我们搜索的内容是掉入狮子笼怎么办呢

GET /test/_search
{
  "query": {
    "match": {
      "name": "掉入狮子笼怎么办"
    }
  }
}

在这里插入图片描述

从搜索结果中我们可以发现,我们明明搜索的是狮子,怎么虱子也搜索出来了?

这说明我们自定义的分词器有问题,在用拼音搜索时确实没问题,但是在用中文搜索时却搜出了同音词

3.8 使用自定义分词器要注意的事项

拼音分词器适合在创建倒排索引的时候使用,但不能在搜索的时候使用


创建倒排索引时

在这里插入图片描述

在这里插入图片描述

用户搜索狮子,搜索结果中居然出现了虱子


所以,我们在创建倒排索引时使用的分词器要和搜索时使用的分词器分开

怎么分开呢,在创建倒排索引时使用 my_analyzer 分词器,搜索时使用 ik_smart 分词器

在这里插入图片描述

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

我们删除 test 索引库之后,重写创建 test 索引库进行测试

DELETE /test
GET /test/_search
{
  "query": {
    "match": {
      "name": "掉入狮子笼怎么办"
    }
  }
}

测试结果如下(可以看到,搜索结果中没有虱子了)

在这里插入图片描述

4. DSL实现自动补全查询

ElasticSearch 提供了 Completion suggester 查询来实现自动补全功能,这个查询会匹配以用户输入内容开头的词条并
返回

4.1 字段的类型的约束

为了提高补全查询的效率,对于文档中字段的类型有一些约束:

  1. 参与补全查询的字段必须是 completion 类型
  2. 字段的内容一般是用来补全的多个词条形成的数组

在这里插入图片描述

4.2 查询语法

在这里插入图片描述

索引库

PUT test2
{
  "mappings": {
    "properties": {
      "title":{
        "type": "completion"
      }
    }
  }
}

测试数据

POST test2/_doc
{
  "title": ["Sony", "WH-1000XM3"]
}

POST test2/_doc
{
  "title": ["SK-II", "PITERA"]
}

POST test2/_doc
{
  "title": ["Nintendo", "switch"]
}

执行查询操作

POST /test2/_search
{
  "suggest": {
    "title_suggest": {
      "text": "s",
      "completion": {
        "field": "title",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

查询结果(查询结果中包含了文档的原始信息)

在这里插入图片描述

5. 自动补全案例

我们来做一个关于酒店数据的自动补全案例

5.1 准备工作

5.1.1 创建hotel索引库

PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_anlyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart",
        "copy_to": "all"
      },
      "address": {
        "type": "keyword",
        "index": false
      },
      "price": {
        "type": "integer"
      },
      "score": {
        "type": "integer"
      },
      "brand": {
        "type": "keyword",
        "copy_to": "all"
      },
      "city": {
        "type": "keyword"
      },
      "starName": {
        "type": "keyword"
      },
      "business": {
        "type": "keyword",
        "copy_to": "all"
      },
      "location": {
        "type": "geo_point"
      },
      "pic": {
        "type": "keyword",
        "index": false
      },
      "all": {
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart"
      },
      "suggestion": {
        "type": "completion",
        "analyzer": "completion_analyzer",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

5.1.2 导入测试工程

测试工程的 Gitee 地址:hotel-demo

5.1.3 导入酒店数据到数据库中

SQL 脚本在测试工程的 doc 目录下

在这里插入图片描述

5.1.4 将数据库中的数据导入到ElasticSearch

导入数据前,更改与连接 ElasticSearch 相关的信息(如果 ElasticSearch 没有设置密码,可以去除 setHttpClientConfigCallback 代码)

在这里插入图片描述

运行 HotelDocumentTest 测试类中的 testBulkRequest 方法,将数据库中的数据导入到 ElasticSearch


在 Kibana 提供的控制台检查数据是否导入成功

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

在这里插入图片描述

5.2 测试自动补全功能

在 Kibana 提供的控制台测试自动补全功能

GET /hotel/_search
{
  "suggest": {
    "suggestions": {
      "text": "s",
      "completion": {
        "field": "suggestion",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

测试结果

在这里插入图片描述

6. RestAPI实现自动补全查询

构建请求参数的 API

在这里插入图片描述

结果解析

在这里插入图片描述

import cn.itcast.hotel.service.IHotelService;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class HotelSuggestionTest {

    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private IHotelService hotelService;

    @Test
    void testSuggestion() throws IOException {
        // 1.准备SearchRequest
        SearchRequest searchRequest = new SearchRequest("hotel");
        // 2.准备DSL
        searchRequest.source().suggest(new SuggestBuilder().addSuggestion(
                "suggestions",
                SuggestBuilders.completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
        ));

        // 3.发送请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // 4.解析结果
        // 4.1.获取suggest对象
        Suggest suggest = searchResponse.getSuggest();
        // 4.2.根据名称获取suggestion对象
        CompletionSuggestion suggestion = suggest.getSuggestion("suggestions");
        // 4.3.获取options
        List<CompletionSuggestion.Entry.Option> options = suggestion.getOptions();
        // 4.4.遍历
        for (CompletionSuggestion.Entry.Option option : options) {
            System.out.println("option.getText().string() = " + option.getText().string());
        }
    }

    @BeforeEach
    void setUp() {
        // 用户名和密码
        String username = "elastic";
        String password = "tF8RGg2vd0FAzgkK";

        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        RestClientBuilder restClientBuilder = RestClient
                .builder(new HttpHost("127.0.0.1", 9200, "http"))
                .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        restHighLevelClient = new RestHighLevelClient(restClientBuilder);
    }

    @AfterEach
    void tearDown() throws IOException {
        restHighLevelClient.close();
    }

}

7. 综合案例:实现搜索框自动补全

测试工程已实现搜索框自动补全,启动测试工程后,在浏览器中查看搜索框的自动补全效果

http://localhost:8089/

在这里插入图片描述


前端源代码的 Gitee 地址:auto-complete

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

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

相关文章

day12 接口测试 ——入门→精通→实战(1)

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、接口测试分类 1.1 内部接口&#xff1a; 1.2 外部接口&#xff1a; 2、目前接口架构设计 2.1、基于SOAP架构&#xff0c; 2.2、基于RPC架构&#xff0c; 2.3、基于RestFul架构&#xff0c; 2.3.1…

54、库卡机器人轴的软限位设置

步骤1&#xff1a;将用户组改为“专家”。 步骤2&#xff1a;点击“投入运行”----“售后服务”-----“软件限位开关” 步骤3&#xff1a;就可以针对每个轴修改对应的角度值&#xff0c;然后点击“保存”。

PHP+MySQL 学生信息管理系统

目录 MySQL建表指令 主页面展示 主页面源代码如下 增&#xff1a;添加学生信息 添加html如下 html&#xff1a;主要用于显示网页内容 成功添加后回显 ​编辑 增加php如下 删&#xff1a;删除学生信息 删除html如下 成功删除后回显 删除php如下 改&#xff1a;修改学…

【第三节】Git 基本操作指南

目录 前言 一、获取与创建项目 1.1 git init 1.2 git clone 二、基本快照操作 2.1 git add 2.2 git status 2.3 git diff 2.4 git commit 2.5 git reset HEAD 三、 文件管理 3.1 git rm 3.2 git mv 四、Git 文件状态 5.1 工作目录 5.2 暂存区 5.3 本地仓库 5…

【第六节】Git Flow:分支管理模型与工作流程

一、Git Flow 简介 1.1 什么是 Git Flow Git Flow 是一种基于 Git 的分支管理模型&#xff0c;旨在帮助团队更好地管理和发布软件。它由 Vincent Driessen 在 2010 年提出&#xff0c;通过一套标准的分支命名和工作流程&#xff0c;使开发、测试和发布过程更加有序和高效。不过…

Windows 与 Linux 下 Ping IPv6 地址 | 常用网络命令

注&#xff1a;本文为网络命令相关文章合辑。 未整理去重。 一、IPv6 概述 IPv6 即 “Internet 协议版本 6”&#xff0c;因 IPv4 地址资源面临耗尽问题而被引入以替代 IPv4。IPv6 则提供了理论上多达 2 128 2^{128} 2128 个地址&#xff0c;有效解决地址不足困境。 IPv6 具…

GB28181系列三:GB28181流媒体服务器ZLMediaKit

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、ZLMediaKit介绍 二、 ZLMediaKit安装、运行(Ubuntu) 1、安装 2、运行 3、配置 三、ZLMediaKit使用 一、ZLMediaKit介绍 ZLMediaKit是一个基于C11的高性能运营级流媒体服务框架&#xff0c;项目地址&#xf…

【深度学习】深刻理解Swin Transformer

Swin Transformer 是一种基于 Transformer 的视觉模型&#xff0c;由 Microsoft 研究团队提出&#xff0c;旨在解决传统 Transformer 模型在计算机视觉任务中的高计算复杂度问题。其全称是 Shifted Window Transformer&#xff0c;通过引入分层架构和滑动窗口机制&#xff0c;S…

uniCloud云开发视频教程-从基础入门到项目开发实战-uniapp进阶课文章管理系统(云函数/云数据库/云存储)

大家好&#xff0c;我是爱搞知识的咸虾米。 今天给大家带来一门uniCloud基础入门到项目开发实战的课程。 视频学习地址&#xff1a;https://www.bilibili.com/video/BV1PP411E7qG/ 开始学习这门课之前&#xff0c;最好先学习一下uniapp零基础入门这套课&#xff0c;相信很多同…

GLB格式转换为STL格式

GLB与STL格式简介 GLB格式 GLB代表“GL传输格式二进制文件”&#xff08;GL Transmission Format Binary&#xff09;。GLB主要用于共享3D数据&#xff0c;包含三维模型、场景、光源、材质、节点层次和动画等详细信息&#xff0c;是一种标准化的文件格式&#xff0c;适用于多…

Qt编译MySQL数据库驱动

目录 Qt编译MySQL数据库驱动 测试程序 Qt编译MySQL数据库驱动 &#xff08;1&#xff09;先找到MySQL安装路径以及Qt安装路径 C:\Program Files\MySQL\MySQL Server 8.0 D:\qt\5.12.12 &#xff08;2&#xff09;在D:\qt\5.12.12\Src\qtbase\src\plugins\sqldrivers\mysql下…

MySQL通过binlog日志进行数据恢复

记录一次阿里云MySQL通过binlog日志进行数据回滚 问题描述由于阿里云远程mysql没有做安全策略 所以服务器被别人远程攻击把数据库给删除&#xff0c;通过查看binlog日志可以看到进行了drop操作&#xff0c;下面将演示通过binlog日志进行数据回滚操作。 1、查询是否开始binlog …

如何在 Ubuntu 22.04 上安装和使用 Rust 编程语言环境

简介 Rust 是一门由 Mozilla 开发的系统编程语言&#xff0c;专注于性能、可靠性和内存安全。它在没有垃圾收集的情况下实现了内存安全&#xff0c;这使其成为构建对性能要求苛刻的应用程序&#xff08;如操作系统、游戏引擎和嵌入式系统&#xff09;的理想选择。 接下来&…

前端项目初始化搭建(二)

一、使用 Vite 创建 Vue 3 TypeScript 项目 PS E:\web\cursor-project\web> npm create vitelatest yf-blog -- --template vue-ts> npx > create-vite yf-blog --template vue-tsScaffolding project in E:\web\cursor-project\web\yf-blog...Done. Now run:cd yf-…

生活小妙招之UE CaptureRT改

需求&#xff0c;四个不同的相机拍摄结果同屏分屏显示 一般的想法是四个Capture拍四张RT&#xff0c;然后最后在面片/UI上组合。这样的开销是创建4张RT&#xff0c;材质中采样4次RT。 以更省的角度&#xff0c;想要对以上流程做优化&#xff0c;4个相机拍摄是必须的&#xff…

【AIGC进阶-ChatGPT提示词副业解析】探索生活的小确幸:在平凡中寻找幸福

引言 在这个快节奏的现代社会中,我们常常被各种压力和焦虑所困扰,忘记了生活中那些细小而珍贵的幸福时刻。本文将探讨如何在日常生活中发现和珍惜那些"小确幸",以及如何通过尝试新事物来丰富我们的生活体验。我们还将讨论保持神秘感和期待感对于维持生活乐趣的重要性…

C#编程报错- “ComboBox”是“...ComboBox”和“...ComboBox”之间的不明确的引用

1、问题描述 在学习使用C#中的Winform平台编写一个串口助手程序时&#xff0c; 在编写一个更新ComboBox列表是遇到了问题&#xff0c;出错的代码是 2、报错信息 CS1503 参数 2: 无法从“System.Windows.Forms.ComboBox”转换为“System.Windows.Forms.ComboBox” CS1503 …

ollama+open-webui,本地部署自己的大模型

目录 一、效果预览 二、部署ollama 1.ollama说明 2.安装流程 2.1 windows系统 2.1.1下载安装包 2.1.2验证安装结果 2.1.3设置模型文件保存地址 2.1.4拉取大模型镜像 2.2linux系统 2.2.1下载并安装ollama 2.2.2设置环境变量 2.2.3拉取模型文件 三、部署open-webui…

leetcode_203. 移除链表元素

203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 开始写的时候没有想明白的问题 1. 开始我是想头节点 尾节点 中间节点 分开处理 如果删除的是头节点 然后又要删除头节点的后继节点 那么 这样子的话头节点分开处理就毫无意义了 接着是尾节点 开始我定义的是curr h…

【大模型微调学习5】-大模型微调技术LoRA

【大模型微调学习5】-大模型微调技术LoRA LoRa微调1.现有 PEFT 方法的局限与挑战2.LoRA: 小模型有大智慧 (2021)3.AdaLoRA: 自适应权重矩阵的高效微调 (2023)4.QLoRA: 高效微调量化大模型 (2023) LoRa微调 1.现有 PEFT 方法的局限与挑战 Adapter方法&#xff0c;通过增加模型深…