Spring Cloud之ElasticSearch的学习【详细】

news2024/10/5 16:30:43

目录

ElasticSearch

正向索引与倒排索引

数据库与elasticsearch概念对比

安装ES、Kibana与分词器

分词器作用

自定义字典

拓展词库

禁用词库

索引库操作

Mapping属性

创建索引库

查询索引库

删除索引库

修改索引库

文档操作

新增文档

查找文档

修改文档

全量修改

增量修改

删除文档

RestClient操作索引库

RestClient操作文档

新增文档

根据Id查询文档数据

更新文档

删除文档

批量新增

DSL查询语法

查询所有

全文检索

精确查询

地理查询

复合查询

搜索结果处理

排序

分页

高亮

RestClient查询文档

查询全部

查询文档

解析数据

全文检索查询

精确查询

复合查询

排序和分页

高亮


ElasticSearch

q:什么是elasticsearch?

a:一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能

q:什么是elastic stack (ELK) ?

a:是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch

q:什么是Lucene?

a:是Apache的开源搜索引擎类库,提供了搜索引擎的核心API

正向索引与倒排索引

在理解正向索引与倒排索引之前,先理解文档与词条的概念

  • 文档(document):每条数据就是一个文档

elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息文档数据会被序列化为json格式后存储在elasticsearch中。

  • 词条(term):文档按照语义分成的词语
  • 索引:相同类型的文档的集合

  • 映射:索引中文档的字段约束信息,类似于表的约束结构

传统数据库比如MySQL使用的是正向索引。通常使用id作为索引

在搜索手机时,如果使用select * from 表 where title like '%手机%';语句进行查找,它会逐条扫描数据,然后找到title中的数据后,判断是否保存”手机“词条。这样的效率很慢.

而elasticsearch采用倒排索引

数据库与elasticsearch概念对比

安装ES、Kibana与分词器

这里是基于Docker的安装,ES也支持windows的安装,具体安装方法请参考其他教程。

首先我们需要将ES与Kibana(为ES提供一个可视化界面)容器互联,因此需要先创建一个网络

输入docker命令

docker network create es-net(es-net网络名称,自己随便起名)
docker pull elasticsearch:版本号
docker pull kibana:版本号(两个版本号需要一致)

docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
--network es-net \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:版本号

之后访问9200端口

出现如下格式证明启动成功。

接下来启动kibana

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
kibana:版本号

启动成功后访问5601端口,出现如下界面

ES默认的分词器对中文分词并不友好。因此我们需要下载IK分词器

下载地址:GitHub - medcl/elasticsearch-analysis-ik: The IK Analysis plugin integrates Lucene IK analyzer into elasticsearch, support customized dictionary.

下在对应版本并解压到刚刚指定的数据卷。

重启容器

docker restart es

IK分词器有两种拆分模式

  • ik_smart:最少切分(空间占用更少)
  • ik_max_word:最细切分(切分力度最大,文档搜索到的概率更大)

下面是两种示例

POST /_analyze
{
  "text":"观察ik分词器的两种模式",
  "analyzer": "ik_max_word"
}

{

"tokens" : [

{

"token" : "观察",

"start_offset" : 0,

"end_offset" : 2,

"type" : "CN_WORD",

"position" : 0

},

{

"token" : "ik",

"start_offset" : 2,

"end_offset" : 4,

"type" : "ENGLISH",

"position" : 1

},

{

"token" : "分词器",

"start_offset" : 4,

"end_offset" : 7,

"type" : "CN_WORD",

"position" : 2

},

{

"token" : "分词",

"start_offset" : 4,

"end_offset" : 6,

"type" : "CN_WORD",

"position" : 3

},

{

"token" : "器",

"start_offset" : 6,

"end_offset" : 7,

"type" : "CN_CHAR",

"position" : 4

},

{

"token" : "的",

"start_offset" : 7,

"end_offset" : 8,

"type" : "CN_CHAR",

"position" : 5

},

{

"token" : "两种",

"start_offset" : 8,

"end_offset" : 10,

"type" : "CN_WORD",

"position" : 6

},

{

"token" : "两",

"start_offset" : 8,

"end_offset" : 9,

"type" : "COUNT",

"position" : 7

},

{

"token" : "种",

"start_offset" : 9,

"end_offset" : 10,

"type" : "CN_CHAR",

"position" : 8

},

{

"token" : "模式",

"start_offset" : 10,

"end_offset" : 12,

"type" : "CN_WORD",

"position" : 9

}

]

}

POST /_analyze
{
  "text":"观察ik分词器的两种模式",
  "analyzer": "ik_smart"
}

{

"tokens" : [

{

"token" : "观察",

"start_offset" : 0,

"end_offset" : 2,

"type" : "CN_WORD",

"position" : 0

},

{

"token" : "ik",

"start_offset" : 2,

"end_offset" : 4,

"type" : "ENGLISH",

"position" : 1

},

{

"token" : "分词器",

"start_offset" : 4,

"end_offset" : 7,

"type" : "CN_WORD",

"position" : 2

},

{

"token" : "的",

"start_offset" : 7,

"end_offset" : 8,

"type" : "CN_CHAR",

"position" : 3

},

{

"token" : "两种",

"start_offset" : 8,

"end_offset" : 10,

"type" : "CN_WORD",

"position" : 4

},

{

"token" : "模式",

"start_offset" : 10,

"end_offset" : 12,

"type" : "CN_WORD",

"position" : 5

}

]

}

分词器作用

  1. 创建倒排索引时对文档分词
  2. 用户搜索时,对输入的内容分词

自定义字典

ik分词器之所以可以实现分词,是内部存在一个字典,根据字典会进行划分。但是有的是时候需要排除某些词语,比如说”嗯“,”哦“等词语,没有划分的意义。又比如说网络梗”打个胶先“等这些不会被识别为一个词语。这个时候我们可以自定义我们的词典。具体修改方式如下。

拓展词库

修改ik分词器插件中的confg目录下的IKAnalyzer.cfg.xml文件

<?xml version="1." encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
	<entry key="ext_dict">ext.dic</entry>
</properties>

禁用词库

<?xml version="1." encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<!--用户可以在这里配置自己的扩展停止词字典 *** 添加停用词词典-->
  <entry key="ext_stopwords">stopword.dic</entry>
</properties>

配置的文件都需要和IKAnalyzer.cfg.xml在同一目录下。如果不存在就自己创建

索引库操作

Mapping属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

  • type:字段数据类型,常见的简单类型有:
    • 字符串: text (可分词的文本)、keyword (精确值,例如:品牌、国家、ip地址)
    • 数值:long、integer、short、byte、double、float
    • 布尔:boolean
    • 日期:date
    • 对象:object
  • index:是否创建索引,默认为true
  • analyzer:使用哪种分词器
  • properties:该字段的子字段

ES还支持两种地理坐标数据类型:

  • geo_point:由维度和经度确定的一个点
  • geo_shape:由多个geo_ponit组成的复杂图形

创建索引库

创建索引库的语法示例如下

PUT /zmbwcx
{
  "mappings": {
    "properties": {
        "info":{
          "type": "text",
          "analyzer": "ik_smart"
        },
        "people":{
          "properties": {
            "name":{
              "type":"keyword"
            },
            "sex":{
              "type":"keyword"
            }
          }
        }
    } 
  }
}

查询索引库

GET /索引库名

删除索引库

DELETE /索引库名

修改索引库

索引库和mapping一旦创建无法进行修改(修改会导致原有的倒排索引发生改变,影响较大,因此无法修改),但是可以向其中添加新的字段

文档操作

新增文档

文档id如果不指定,会随机生成一个文档id

POST /zmbwcx/_doc/1
{
  "info":"成功人士",
  "people":{
    "name":"zmbwcx",
    "sex":"男"
  }
}

查找文档

GET /索引库名/_doc/文档id

字段解读:

  • _index:索引库名
  • _type:查询类型
  • _id:文档id
  • _version:查询次数
  • _source:文档内容

修改文档

全量修改

删除旧文档,添加新文档。具体操作和新增文档相同,只有请求由POST变为PUT。如果修改的文档id不存在,则相当于新增

PUT /索引库名/_doc/文档id
{
  "字段1":"值1",
  "字段2":"值2",
	// ...略
}

增量修改

POST /索引库名/_update/文档id
{
	"doc":{
      "字段名":"新的值"
	}
}

删除文档

DELETE /索引库名/_doc/文档id

RestClient操作索引库

资料下载:https://pan.baidu.com/s/1ORJ-jERwZzJMoyWpCrgafw?pwd=zmbw

mapping要考虑的问题:字段名、数据类型、是否参与搜索、是否分词、如果分词,分词器是什么?

字段名与数据类型的设计与数据库一样就可以。其余的部分要联合业务决定

具体DSL语句如下,我们可以选择在视图界面直接运行如下代码也可以在Java中创建索引库。

PUT /hotel
{
  "mappings":{
    "properties":{
      "id":{
        "type":"keyword"
      },
      "name":{
        "type":"text",
        "analyzer":"ik_max_word",
        "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": "ik_max_word"
      }
    }
  }
}

如果需要实现搜索一个字段可以查询到多个字段的内容需要使用字段拷贝。

"拷贝字段":{
	"type":"test",
  "analyzer":"ik_max_word"
},
"被拷贝字段":{
	"copy_to":"拷贝字段"
}

创建好mapping映射后,编写Java部分的代码

首先引入依赖,这里的版本一定要和docker中安装的版本一样

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
<dependencies>
	<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
  </dependency>
</dependencies> 

创建客户端对象,并使用该对象创建索引库。

@SpringBootTest
class HotelDemoApplicationTests {
    private RestHighLevelClient client;

    @BeforeEach//初始化客户端
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.116.131:9200")
        ));
    }

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

    @Test//创建索引库
    public void testCreateIndex() throws Exception {
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);
    }
       
    @Test//删除索引库
    public void testDeleteIndex() throws Exception {
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        client.indices().delete(request,RequestOptions.DEFAULT);
    }

    @Test//判断索引库是否存在
    public void testGetIndex() throws Exception {
        GetIndexRequest request = new GetIndexRequest("hotel");
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists?"索引库存在":"索引库不存在");
    }
}

RestClient操作文档

新增文档

@SpringBootTest
class TestDoc {
    private RestHighLevelClient client;
    @Autowired
    private IHotelService service;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.116.131:9200")
        ));
    }

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

    @Test
    public void testInsertDoc() throws Exception {
        //从数据库中查找数据
        Hotel hotel = service.getById(36934);
        //转换为Mapping相对应的格式
        HotelDoc hotelDoc = new HotelDoc(hotel);
        //创建添加请求
        IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
        //准备JSON文档
        request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
        //添加文档
        client.index(request,RequestOptions.DEFAULT);
    }
}

 去可视化界面查询是否插入成功

根据Id查询文档数据

    @Test
    public void testGetResultById() throws Exception {
        GetRequest request = new GetRequest("hotel","36934");
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        String jsonStr = response.getSourceAsString();
        HotelDoc hotelDoc = JSON.parseObject(jsonStr, HotelDoc.class);
        System.out.println(hotelDoc);
    }

更新文档

更新文档有两种,一种是全量更新,更改方式与新增文档一模一样。

另一种是局部更新,代码如下

    @Test
    public void testUpdateDoc() throws Exception {
        UpdateRequest request = new UpdateRequest("hotel","36934");
        //参数类似于k:v,但不同的是,不是使用:而是,分割,每两个作为一个kv。第三个参数作为k
        request.doc(
                "price","300"
        );
        client.update(request,RequestOptions.DEFAULT);
    }

删除文档

    @Test
    public void testDeleteDoc() throws Exception {
        DeleteRequest request = new DeleteRequest("hotel","36934");
        client.delete(request,RequestOptions.DEFAULT);
    }

批量新增

    @Test
    public void testInsertDocs() throws Exception {
        List<Hotel> list = service.list();
        List<HotelDoc> listHotelDocs = list.stream().map(hotel -> new HotelDoc(hotel)).collect(Collectors.toList());
        BulkRequest bulkRequest = new BulkRequest();
        for (HotelDoc hotelDoc : listHotelDocs) {
            bulkRequest.add(new IndexRequest("hotel")
                    .id(hotelDoc.getId().toString())
                    .source(JSON.toJSONString(hotelDoc),XContentType.JSON));
        }
        client.bulk(bulkRequest,RequestOptions.DEFAULT);
    }

DSL查询语法

查询所有

但实际上有条数限制,为10条

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

全文检索

会对用户输入的数据经过分词器处理后搜索文档,常用于搜索框

一种是match搜索

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "北京"
    }
  }
}

一种是multi_match,可以查询多个字段

GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "北京如家",
      "fields": ["brand","name","business"]
    }
  }
}

两种查询效果基本相同,但第二种查询的索引更多,速度更慢些,所以更推荐通过拷贝的方式只查询一个索引。

精确查询

精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词。

  • term:根据词条精确值查询
  • range:根据值的范围查询

查询北京地区的旅店信息

GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "北京"
      }
    }
  }
}

查询价格区间的旅店信息

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}

地理查询

geo_bounding_box查询方式。

geo_distance查询方式

复合查询

复合查询可以将其他简单的查询组合起来,实现更复杂的搜索逻辑

fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名

boolean query:布尔查询是一个或多个查询子句的组合。子查询的组合方式有

  • must:必须匹配每个子查询,类似”与“
  • should:选择性匹配子查询,类似”或“
  • must_not:必须不匹配,不参与算分,类似”非“
  • filter:必须匹配,不参与算分

参与算分的条件越多,性能越差

搜索结果处理

排序

默认根据相关度算分(_score)排序,但是可以自定义排序规则,比如说价格,或是日期,如果指定其他排序,则放弃算分,性能更好

按用户评分降序,价格升序查询

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": "desc"
    },
    {
      "price": "asc"
    }
  ]
}

分页

ES中默认一次查询出10条数据。如果需要获取更多的数据,需要修改分页参数

#分页查询
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from": 10, //从第十条开始查找
  "size": 20 //查询20条数据
}

分页存在的问题:

ES和数据库不同,ES做的是逻辑分页,也就是查询出前30条数据,然后截取10之后的20条数据。其次,ES通常为了存储更多文档都是集群工作,会将文档拆分到不同节点上。如果我们以价格升序排序后,截取50-60的文档,那么实际上是每个节点都进行排序后,每个节点数据集合到内存后再次重新排序后再去截取50-60的数据。

如果搜索的页数过深,或者结果集(from+size)过大,对内存和CPU消耗越高,因此ES设定结果集上限为1000

高亮

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "北京"
    }
  },
  "highlight": {
    "fields": {
      "name": {
        "require_field_match": "false" //取消字段匹配
      }
    }
  }
}

ES默认情况下ES的搜索字段必须与高亮字段名一致。如果不需要一致,则需要添加配置

RestClient查询文档

查询全部

查询文档

    @Test
    public void testSearchMatchAll() throws Exception {
        SearchRequest request = new SearchRequest("hotel");
        //准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

解析数据

结合JSON格式进行解析数据

    @Test
    public void testSearchMatchAll() throws Exception {
        SearchRequest request = new SearchRequest("hotel");
        //准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response);
        SearchHits searchHits = response.getHits();
        long totalNum = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
            System.out.println(hotelDoc);
        }
        System.out.println("一共查询到:"+totalNum+"条");
    }

全文检索查询

    @Test
    public void testSearchMatch() throws Exception {
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.matchQuery("all","北京"));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        long totalNum = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
            System.out.println(hotelDoc);
        }
        System.out.println("一共查询到:"+totalNum+"条");
    }

与MatchAll的查询方式基本无异。多了个指定字段与查询内容

精确查询

复合查询

排序和分页

    @Test
    public void testSearchPage() throws Exception {
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.matchQuery("all","北京"));
        request.source().from(10).size(5);
        request.source().sort("price", SortOrder.ASC);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        long totalNum = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
            System.out.println(hotelDoc);
        }
        System.out.println("一共查询到:"+totalNum+"条");
    }

高亮

    @Test
    public void testHighLight() throws Exception {
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.matchQuery("all","北京"));
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)){
                HighlightField field = highlightFields.get("name");
                if (field!=null){
                    String value = field.getFragments()[0].string();
                    hotelDoc.setName(value);
                }
            }
            System.out.println(hotelDoc);
        }
    }

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

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

相关文章

安卓平板-学习平板、三防工业平板安卓主板方案

近年来&#xff0c; 生活和工业产品的需求呈爆发式增长&#xff0c;学习平板、工业平板和智能设备的出货量正处于快速增长的阶段。尤其是安卓平板智能设备&#xff0c;其增长势头依然迅猛。根据预测&#xff0c;到2024年&#xff0c;中国平板设备的总出货量将会进一步增长。 安…

顺序表(1)

目录 线性表 顺序表Sequential List 静态顺序表 动态顺序表 主函数Test.c test1 test2 test3 test4 头文件&函数声明SeqList.h 头文件 函数声明 函数实现SeqList.c 初始化SLInit 释放销毁SLDestroy 扩容SLCheckCapacity 打印SLPrint 尾插SLPushBack …

“智能科技·链接未来”2024中国国际人工智能产品展览会·智博会

2024年中国国际人工智能产品展览会&#xff08;简称世亚智博会&#xff09;将于3月份在上海举办&#xff0c;6月份在北京举办。本届展会以“智能科技链接未来”为主题&#xff0c;将集中展示全球前沿的人工智能技术和应用&#xff0c;以及人工智能在各个领域的新成果。 本届展会…

Unity 粒子特效-第二集-烟雾特效

一、烟雾特效预览 二、制作原理 资源在绑定资源里&#xff0c;我得审核通过以后才能改成免费&#xff0c;如果着急要&#xff0c;可以评论区发一下&#xff0c;我给你们发网盘 1.这个是序列帧图片粒子特效一起组合而成的 这就是一个单独整个的烟雾动画 如下&#xff0c;是这…

Google Play上的Android广告软件应用程序积累了200万次安装

大家好&#xff0c;今天我们要聊一聊Google Play上的一个热门话题——Android广告软件应用程序。最近&#xff0c;一些恶意应用程序在Google Play上累积了200万次的安装量&#xff0c;给用户推送了讨厌的广告&#xff0c;同时又隐藏了它们在受感染设备上的存在。 根据Doctor W…

保护生产中 Node.js 应用程序安全的 15 项最佳实践

在后端开发方面&#xff0c;Node.js 是开发人员最喜欢的技术之一。它的受欢迎程度不断上升&#xff0c;现已成为在线攻击的主要目标之一。这就是为什么保护 Node.js 免受漏洞和威胁至关重要。 在本指南中&#xff0c;您将看到为生产设计安全 Node.js 应用程序架构的 15 种最佳…

安防视频监控平台EasyCVR前端解码与后端解码的区别介绍

视频监控平台/视频存储/视频分析平台EasyCVR基于云边端一体化管理&#xff0c;支持多类型设备、多协议方式接入&#xff0c;具体包括&#xff1a;国标GB28181协议、RTMP、RTSP/Onvif、海康Ehome&#xff0c;以及海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石SDK等&#x…

linux中etc目录中常用文件

1.查看当前系统版本信息情况 cat /etc/redhat-release 版本是7.5 2.查看当前系统用户基本信息文件 cat /etc/passwd 3.查看当前系统主机名配置文件 cat /etc/hostname 可以更改主机名 方法一&#xff1a;临时修改方法&#xff0c;退出后重新连接即可生效 语…

云服务器安装Hive

文章目录 1. 安装Hive(最小化部署)2. MySQL安装3. Hive元数据配置到MySQL4. HiveServer2服务5. Metastore服务运行模式6. 编写脚本来管理hive的metastore/hiveserver2服务的启动和停止1.7 Hive常用命令 7. Hive参数配置方式7.1 Hive常见的几个属性配置 安装Hive的前提是先安装H…

通信原理板块——卷积码(原理、代数和几何表示、编码和解码)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、卷积码定义 卷积码(convolution…

Python--快速入门一

Python--快速入门一 1.创建Python的项目 使用IDE&#xff1a;PyCharm 创建项目文件夹&#xff1a; 点击新建项目 将位置地址改为想要Python项目存放的位置 基础解释器选择最新版本的解释器&#xff08;此处为Python3.120 关闭创建main.py(此功能是自动一个初始文件&#x…

[量化投资-学习笔记004]Python+TDengine从零开始搭建量化分析平台-EMA均线

在之前的文章中用 Python 直接计算的 MA 均线&#xff0c;但面对 EMA 我认怂了。 PythonTDengine从零开始搭建量化分析平台-MA均线的多种实现方式 高数是我们在大学唯一挂过的科。这次直接使用 Pandas 库的 DataFrame.ewm 函数&#xff0c;便捷又省事。 并且用 Pandas 直接对之…

【ElasticSearch系列-02】ElasticSearch的概念和基本操作

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631 深入理解ElasticSearch概念和基本操…

建筑模板-优质建筑模板厂家推荐

随着建筑行业的不断发展&#xff0c;优质的建筑模板成为了保障工程施工质量的重要一环。在众多建筑模板厂家中&#xff0c;广西贵港市能强优品木业凭借其优质的产品和良好的口碑赢得了业界的认可与信赖。 广西贵港市能强优品木业是一家专注于建筑模板生产的企业&#xff0c;公司…

#stm32整理(二)关于MDK的编译过程及文件类型全解

参考野火开发指南如有侵权即刻删除&#xff0c;只是为了学习交流使用 1、编译 1、编译过程简介 (1&#xff09;编译&#xff0c;MDK 软件使用的编译器是 armcc 和 armasm&#xff0c;它们根据每个 c/c 和汇编源文件编译 成对应的以“.o”为后缀名的对象文件 (Object Code&…

设计模式—创建型模式之工厂模式

设计模式—创建型模式之工厂模式 工厂模式&#xff08;Factory Pattern&#xff09;提供了一种创建对象的最佳方式。我们不必关心对象的创建细节&#xff0c;只需要根据不同情况获取不同产品即可。 简单工厂模式 比如我们有造车的工厂&#xff0c;来生产车&#xff0c;我们先…

b站so层sign算法

前言 大家好呀,欢迎来到我的博客!!! 本期我将带来b站so层sign算法实现 设备: pixel4 android10 下载地址: aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzI4MTI5MS9oaXN0b3J5X3Y2MTgwNTAw 版本: 6.18.0 工具: charles(抓包) socksdroid(流量转发) jadx(反编译dex) ida(反编…

中微CMS8S3680/69xx系列单片机

最近在使用中微CMS8S3680/69xx系列8位单片机来进行电源控制软件开发。 总体觉得这款单片机简单易用&#xff0c;特别是它的数字功能可以映射到任意脚&#xff0c;甚至包括程序的烧录脚&#xff0c;对于PCB布局特别灵活。另外它的存储器资源也是很丰富的&#xff0c;16K字节ROM…

实战 | SQL注入

一、资产搜集 我们都知道sql注入的传参有些是明文的&#xff0c;有些是经过编码或者加密的&#xff0c;所以我们搜索的时候不要仅限于inurl:.php?id1&#xff0c;可以额外的尝试搜搜1的base64编码值MQ&#xff0c;即可以搜索inurl:.php?idMQ&#xff0c;或者搜索1的md5加密值…