学习笔记:ElasticSearch搜索引擎

学习视频:【尚硅谷】ElasticSearch教程入门到精通(基于ELK技术栈elasticsearch 7.x+8.x新特性)
学习笔记:Elasticsearch学习笔记

目录

  • 第1章 Elasticsearch概述
    • 01. 开篇
    • 02. 技术选型
  • 2. 第二章 ElasticSearch入门
    • 03. 环境准备
    • 04. RESTful & JSON
    • 05. 倒排索引
    • 06. HTTP-索引-创建
    • 07. HTTP-索引-查询 & 删除
    • 08. HTTP-文档-创建(Put & Post)
    • 09. HTTP-文档-主键查询 & 全查询
    • 10. HTTP-文档-全量修改 & 局部修改 & 删除
    • 11. HTTP-文档-条件查询 & 字段查询 & 分页查询 & 查询排序
    • 12. HTTP-文档-多条件查询 & 范围查询
    • 13. HTTP-文档-全文检索 & 完全匹配 & 高亮查询
    • 14. HTTP-文档-聚合查询
    • 15. HTTP-映射-创建 & 查询 & 使用
    • 16. JavaAPI-环境准备
  • 3. 第三章 SpringData集成
  • 4. 第四章 SparkStreaming集成ES
  • 5. 第五章 Flink集成ES


第1章 Elasticsearch概述

01. 开篇

Elastic表示可伸缩、灵活的意思。互联网中查询的信息主要包括文章、视频、图片、网站信息等等,按数据格式分为以下三大类:

  • 结构化数据:按特定结构和组织管理数据,一般表现为二维表结构(比如用户数据,包括用户姓名、年龄、身份证号)。可以保存到关系型数据库(MySQL、Oracle),优点是方便管理和查询,缺点是扩展难
    在这里插入图片描述
  • 非结构化数据:无法用二维表结构表现的数据(如服务器日志、通信记录、文档、报表、视频、图片等)。维度广数据量大,数据存储查询成本大,需要专业人员和大量统计模型进行处理,一般会将这类数据存储于NoSQL数据库中(MongoDB、Redis、Hbase),一般按KV结构进行保存
    在这里插入图片描述
  • 半结构化数据:将数据内容和结构混合在一起,没有明显区分(如XML、HTML等)。一般保存在NoSQL数据库中(MongoDB、Redis、Hbase),缺点是查询其中内容并不容易
    在这里插入图片描述

准确快速地查询结构化数据和非结构化数据当中的内容,是非常重要的。实时数据的采集、分析、存储是未来计算机处理技术发展的方向,ES在这些方面表现良好

02. 技术选型

Elasticsearch 是什么
The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。

Elaticsearch,简称为 ES, ES 是一个开源的高扩展的分布式全文搜索引擎, 是整个 ElasticStack 技术栈的核心。

它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。

elastic
英 [ɪˈlæstɪk] 美 [ɪˈlæstɪk]
n. 橡皮圈(或带);松紧带
adj. 橡皮圈(或带)的;有弹性的;有弹力的;灵活的;可改变的;可伸缩的

全文搜索引擎
Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。

一般传统数据库,全文检索都实现的很鸡肋,因为一般没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:

  • 搜索的数据对象是大量的非结构化的文本数据。
  • 文件记录量达到数十万或数百万个甚至更多。
  • 支持大量基于交互式文本的查询。
  • 需求非常灵活的全文搜索查询。
  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎 。

这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

Elasticsearch 应用案例

  • GitHub: 2013 年初,抛弃了 Solr,采取 Elasticsearch 来做 PB 级的搜索。 “GitHub 使用Elasticsearch 搜索 20TB 的数据,包括 13 亿文件和 1300 亿行代码”。
  • 维基百科:启动以 Elasticsearch 为基础的核心搜索架构
  • 百度:目前广泛使用 Elasticsearch 作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部 20 多个业务线(包括云分析、网盟、预测、文库、直达号、钱包、 风控等),单集群最大 100 台机器, 200 个 ES 节点,每天导入 30TB+数据。
  • 新浪:使用 Elasticsearch 分析处理 32 亿条实时日志。
  • 阿里:使用 Elasticsearch 构建日志采集和分析体系。
  • Stack Overflow:解决 Bug 问题的网站,全英文,编程人员交流的网站。

2. 第二章 ElasticSearch入门

03. 环境准备

  • 官方网址:https://www.elastic.co/cn/
  • 官方文档: https://www.elastic.co/guide/index.html
  • 下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-7-8-0

解压后的 Elasticsearch 的目录结构如下 :

目录含义
bin可执行脚本目录
config配置目录
jdk内置 JDK 目录
lib类库
logs日志目录
modules模块目录
plugins插件目录

解压后,进入 bin 文件目录,启动 ES 服务 。

注意: 9300 端口为 Elasticsearch 集群间组件的通信端口, 9200 端口为浏览器访问的 http协议 RESTful 端口。

打开浏览器,输入地址:http://localhost:9200,测试返回结果,返回结果如下:

{"name" : "DESKTOP-LNJQ0VF","cluster_name" : "elasticsearch","cluster_uuid" : "nCZqBhfdT1-pw8Yas4QU9w","version" : {"number" : "7.8.0","build_flavor" : "default","build_type" : "zip","build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65","build_date" : "2020-06-14T19:35:50.234439Z","build_snapshot" : false,"lucene_version" : "8.5.1","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

04. RESTful & JSON

特定互联网软件架构原则——REST原则,REST表示资源状态转换,请求资源存在状态,该状态根据原则进行转换,符合此原则的就是RESTful

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。 Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。

在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、 PUT、 POST 和DELETE。

在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目
标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、 POST、PUT、 DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径, 以及对资源进行的操作(增删改查)

REST 样式的 Web 服务若有返回结果,大多数以JSON字符串形式返回。

05. 倒排索引

正排索引(传统)

idcontent
1001my name is zhang san
1002my name is li si

倒排索引

keywordid
name1001, 1002
zhang1001

Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。 为了方便大家理解,我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比:
在这里插入图片描述

ES 里的 Index 可以看做一个库,而 Types 相当于表, Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化, Elasticsearch 6.X 中,一个 index 下已经只能包含一个type, Elasticsearch 7.X 中, Type 的概念已经被删除了。

06. HTTP-索引-创建

对比关系型数据库,创建索引就等同于创建数据库。

在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/shopping
请求后,服务器返回响应:

{"acknowledged": true, // 响应结果"shards_acknowledged": true, // 分片结果"index": "shopping" // 索引名称
}

后台日志:

[2021-04-08T13:57:06,954][INFO ][o.e.c.m.MetadataCreateIndexService] [DESKTOP-LNJQ0VF] [shopping] creating index, cause [api], templates [], shards [1]/[1], mappings []

如果重复发 PUT 请求 : http://127.0.0.1:9200/shopping 添加索引,会返回错误信息 :

{"error": {"root_cause": [{"type": "resource_already_exists_exception","reason": "index [shopping/J0WlEhh4R7aDrfIc3AkwWQ] already exists","index_uuid": "J0WlEhh4R7aDrfIc3AkwWQ","index": "shopping"}],"type": "resource_already_exists_exception","reason": "index [shopping/J0WlEhh4R7aDrfIc3AkwWQ] already exists","index_uuid": "J0WlEhh4R7aDrfIc3AkwWQ","index": "shopping"},"status": 400
}

07. HTTP-索引-查询 & 删除

查看所有索引
在 Postman 中,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/_cat/indices?v

这里请求路径中的_cat 表示查看的意思, indices 表示索引,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉,服务器响应结果如下 :

health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   shopping J0WlEhh4R7aDrfIc3AkwWQ   1   1          0            0       208b           208b
表头含义
health当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
status索引打开、关闭状态
index索引名
uuid索引统一编号
pri主分片数量
rep副本数量
docs.count可用文档数量
docs.deleted文档删除状态(逻辑删除)
store.size主分片和副分片整体占空间大小
pri.store.size主分片占空间大小

查看单个索引
在 Postman 中,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping

返回结果如下:

{"shopping": {//索引名"aliases": {},//别名"mappings": {},//映射"settings": {//设置"index": {//设置 - 索引"creation_date": "1617861426847", // 设置 - 索引 - 创建时间"number_of_shards": "1", // 设置 - 索引 - 主分片数量"number_of_replicas": "1", // 设置 - 索引 - 主分片数量"uuid": "J0WlEhh4R7aDrfIc3AkwWQ", // 设置 - 索引 - 主分片数量"version": { // 设置 - 索引 - 主分片数量"created": "7080099"},"provided_name": "shopping" // 设置 - 索引 - 主分片数量}}}
}

删除索引
在 Postman 中,向 ES 服务器发 DELETE 请求:http://127.0.0.1:9200/shopping

返回结果如下:

{"acknowledged": true
}

再次查看所有索引,GET http://127.0.0.1:9200/_cat/indices?v,返回结果如下:

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size

成功删除。

08. HTTP-文档-创建(Put & Post)

假设索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式

在 Postman 中,向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_doc,请求体JSON内容为:

{"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00
}

在这里插入图片描述
注意:此处发送请求的方式必须为 POST,不能是 PUT,否则会发生错误 。(因为PUT为幂等性操作)

返回结果:

{"_index": "shopping", // 索引"_type": "_doc",      // 类型-文档"_id": "HlZVAZABiRKfiqMg-gkO", // 唯一标识,类似MySQL的主键,随机生成"_version": 1,		  // 版本"result": "created",  // 结果,created表示创建成功"_shards": {"total": 2,		  // 分片-总数"successful": 1,  // 分片-总数"failed": 0		  // 分片-总数},"_seq_no": 0,"_primary_term": 1
}

上面的数据创建后,由于没有指定数据唯一性标识(ID),默认情况下, ES 服务器会随机生成一个。

如果想要自定义唯一性标识,需要在创建时指定:http://127.0.0.1:9200/shopping/_doc/1localhost:9200/shopping/_create/1,请求体JSON内容为:

{"_index": "shopping","_type": "_doc","_id": "1",		// 唯一标识为 1"_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1
}

注意:如果增加数据时明确数据主键,那么请求方式也可以为 PUT。

09. HTTP-文档-主键查询 & 全查询

主键查询
查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询
在 Postman 中,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_doc/1

返回结果:

{"_index": "shopping","_type": "_doc","_id": "1","_version": 15,"_seq_no": 17,"_primary_term": 1,"found": true,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}
}

查找不存在的内容,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_doc/9

返回结果:

{"_index": "shopping","_type": "_doc","_id": "1001","found": false
}

全部查询

查看索引下所有数据,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search

返回结果:

{"took": 4,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 3,"relation": "eq"},"max_score": 1.0,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 1.0,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00}},{"_index": "shopping","_type": "_doc","_id": "1","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}}]}
}

10. HTTP-文档-全量修改 & 局部修改 & 删除

全量修改

和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖。

在 Postman 中,向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_doc/1
请求体JSON内容为:

{"title":"华为手机","category":"华为","images":"http://www.gulixueyuan.com/hw.jpg","price":1999.00
}

返回结果:

{"_index": "shopping","_type": "_doc","_id": "1","_version": 2,"result": "updated", // <-----------updated 表示数据被更新"_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 2,"_primary_term": 1
}

局部修改

修改数据时,也可以只修改某一条数据的局部信息。

在 Postman 中,向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_update/1
请求体JSON内容为:

{"doc": {"title": "小米手机","category": "小米"}
}

返回结果如下:

{"_index": "shopping","_type": "_doc","_id": "1","_version": 3,"result": "updated",//<-----------updated 表示数据被更新"_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 3,"_primary_term": 1
}

删除

删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。

在 Postman 中,向 ES 服务器发 DELETE 请求:http://127.0.0.1:9200/shopping/_doc/1

返回结果:

{"_index": "shopping","_type": "_doc","_id": "1","_version": 23,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 25,"_primary_term": 1
}

11. HTTP-文档-条件查询 & 字段查询 & 分页查询 & 查询排序

条件查询(URL携带参数)

查找category为小米的文档,在 Postman 中,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search?q=category:小米

返回结果:

{"took": 25,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": 0.36464313,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 0.36464313,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 0.36464313,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00}}]}
}

上述为URL带参数形式查询,这很容易让心怀恶意者钻空子,或者参数值出现中文会出现乱码情况。为了避免这些情况,我们可用使用带JSON请求体请求进行查询。

条件查询(请求体携带参数)

接下带JSON请求体,还是查找category为小米的文档,在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query": {"match": {"category": "小米"}}
}

返回结果与之前一致

查询全部(请求体方式)

查找所有文档内容,也可以这样,在 Postman 中,向 ES 服务器发 GET请求 : http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query":{"match_all":{}}
}

返回结果:

{"took": 2,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": 1.0,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 1.0,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00}}]}
}

查询指定字段

如果你想查询指定字段,在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query":{"match_all":{}},"_source":["title"]
}

返回结果如下:

{"took": 8,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": 1.0,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0,"_source": {"title": "小米14"}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 1.0,"_source": {"title": "小米13"}}]}
}

分页查询

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query": {"match_all": {}},"from": 0, // 页码数-1"size": 1  // 显示多少条
}

返回结果:

{"took": 1,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": 1.0,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}}]}
}

查询排序

如果你想通过排序查出价格最高的手机,在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query": {"match_all": {}},"sort": {"price": {"order": "desc"}}
}

返回结果:

{"took": 9,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": null,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": null,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00},"sort": [3999.0]},{"_index": "shopping","_type": "_doc","_id": "2","_score": null,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00},"sort": [3599.0]}]}
}

12. HTTP-文档-多条件查询 & 范围查询

多条件查询——MUST

假设想找出小米牌子,价格为3999元的。

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:(must相当于MySQL的AND)

{"query": {"bool": {"must": [{"match": {"category": "小米"}},{"match": {"price": 3999}}]}}
}

返回结果:

{"took": 13,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 1,"relation": "eq"},"max_score": 1.3646431,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.3646431,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}}]}
}

多条件查询——SHOULD

假设想找出小米和华为的牌子。

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:(should相当于MySQL的OR)

{"query": {"bool": {"should": [{"match": {"category": "小米"}},{"match": {"category": "华为"}}]}}
}

返回结果:

{"took": 9,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 4,"relation": "eq"},"max_score": 1.7509375,"hits": [{"_index": "shopping","_type": "_doc","_id": "3","_score": 1.7509375,"_source": {"title": "HUAWEI Pura 70","category": "华为","images": "https://res2.vmallres.com/pimages/uomcdn/CN/pms/202405/displayProduct/10086157311748/428_428_a_web628062479CFC08B72883649F8B058507.jpg","price": 5499.00}},{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0779929,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 1.0779929,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00}},{"_index": "shopping","_type": "_doc","_id": "1","_score": 1.0779929,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}}]}
}

范围查询

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query": {"bool": {"should": [{"match": {"category": "小米"}},{"match": {"category": "华为"}}],"filter": {"range": {"price": {"gt": 5000}}}}}
}

13. HTTP-文档-全文检索 & 完全匹配 & 高亮查询

全文检索

这功能像搜索引擎那样,如品牌输入“小华”,返回结果带回品牌有“小米”和华为的。

在 Postman 中,向 ES 服务器发 GET请求 : http://127.0.0.1:9200/shopping/_search,请求体附带JSON体如下:

{"query": {"match": {"category" : "小华"}}
}

完全匹配

如果想要完全匹配才能命中,返回品牌有“小华”的。

在 Postman 中,向 ES 服务器发 GET请求 : http://127.0.0.1:9200/shopping/_search,请求体附带JSON体如下:

{"query": {"match_phrase": {"category" : "小华"}}
}

高亮查询
在 Postman 中,向 ES 服务器发 GET请求 : http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"query": {"bool": {"must": [{"match_phrase": {"category": "为"}}]}},"highlight": {"fields": {"category": {} // <----高亮此字段}}
}

14. HTTP-文档-聚合查询

聚合允许使用者对 ES 文档进行统计分析,类似与关系型数据库中的 group by,当然还有很多其他的聚合,例如取最大值max、平均值avg等等。

分组查询

接下来按price字段进行分组:

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"aggs":{ // 聚合操作"price_group":{ // 名称,随意起"terms":{ // 分组"field": "price" // 分组字段}}}
}

返回结果:

{"took": 6,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 4,"relation": "eq"},"max_score": 1.0,"hits": [{"_index": "shopping","_type": "_doc","_id": "HlZVAZABiRKfiqMg-gkO","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}},{"_index": "shopping","_type": "_doc","_id": "2","_score": 1.0,"_source": {"title": "小米13","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1670745532.86084186.png","price": 3599.00}},{"_index": "shopping","_type": "_doc","_id": "3","_score": 1.0,"_source": {"title": "HUAWEI Pura 70","category": "华为","images": "https://res2.vmallres.com/pimages/uomcdn/CN/pms/202405/displayProduct/10086157311748/428_428_a_web628062479CFC08B72883649F8B058507.jpg","price": 5499.00}},{"_index": "shopping","_type": "_doc","_id": "1","_score": 1.0,"_source": {"title": "小米14","category": "小米","images": "https://cdn.cnbj0.fds.api.mi-img.com/b2c-shopapi-pms/pms_1698304477.56836008.png","price": 3999.00}}]},"aggregations": {"price_group": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": 3999.0,"doc_count": 2},{"key": 3599.0,"doc_count": 1},{"key": 5499.0,"doc_count": 1}]}}
}

上面返回结果会附带原始数据的。若不想要不附带原始数据的结果,在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"aggs": { // 聚合操作"price_group": { // 名称,随意起"terms": { // 分组"field": "price" // 分组字段}}},"size": 0 // 排除原始数据结果
}

求平均值

对所有手机价格求平均值。

在 Postman 中,向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带JSON体如下:

{"aggs": { // 聚合操作"price_avg": { // 名称,随意起"avg": { // 平均值"field": "price" // 分组字段}}},"size": 0 // 排除原始数据结果
}

返回结果:

{"took": 4,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 4,"relation": "eq"},"max_score": null,"hits": []},"aggregations": {"price_avg": {"value": 4274.0}}
}

15. HTTP-映射-创建 & 查询 & 使用

有了索引库,等于有了数据库中的 database。

接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。

创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。

先创建一个索引:

PUT http://127.0.0.1:9200/user

创建映射

PUT http://127.0.0.1:9200/user/_mapping{"properties": {"name": {"type": "text",  // 支持全文检索"index": true},"sex": {"type": "keyword", // 需要完全匹配"index": true},"tel": {"type": "keyword", // 需要完全匹配"index": false}}
}

查询映射

GET http://127.0.0.1:9200/user/_mapping

返回结果:

{"user": {"mappings": {"properties": {"name": {"type": "text","index": true},"sex": {"type": "keyword","index": true},"tel": {"type": "keyword","index": false}}}}
}

此时插入数据:

PUT localhost:9200/user/_create/1{"name": "ziang","sex": "male","tel": 13716004539
}

测试以下三条示例请求

  • 请求1:

    GET http://127.0.0.1:9200/user/_search
    {"query":{"match":{"name":"zi"}}
    }
    
  • 请求2:

    GET http://127.0.0.1:9200/user/_search
    {"query":{"match":{"sex":"ma"}}
    }
    
  • 请求3:

    GET http://127.0.0.1:9200/user/_search
    {"query":{"match":{"tel":"1371600"}}
    }
    

请求1可以查询出数据,但请求2不可以,因为创建映射时 “sex” 的类型为 “keyword”,需要完全匹配才能查询出来。请求3查询报错,因为创建映射时 “tel” 的 “index” 为 false。

16. JavaAPI-环境准备

新建Maven工程。添加依赖:

<dependencies><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</version></dependency><!-- elasticsearch 的客户端 --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.8.0</version></dependency><!-- elasticsearch 依赖 2.x 的 log4j --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.8.2</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.8.2</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.9</version></dependency><!-- junit 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies>

ElasticSearch示例Gitee地址: https://gitee.com/dreamPointer/dreampointer.git,在demo-elasticsearch下


3. 第三章 SpringData集成

Spring Data 是一个用于简化数据库访问和增加数据访问层功能性的项目家族。它为各种数据存储(如关系型数据库、NoSQL数据库、云服务等)提供了统一的编程模型。Spring Data 的主要目标是使开发者能够更容易地构建Spring驱动的应用程序,而无需编写大量的数据访问代码。

对于关系型数据库,Spring Data JPA 是最常用的实现之一,它基于Java Persistence API (JPA) 提供了额外的功能。Spring Data可以极大的简化JPA(Elasticsearch…)的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD 外,还包括如分页、排序等一些常用的功能。

但Spring Data 的理念不仅限于JPA,它还为MongoDB、Cassandra、Redis等多种数据存储提供了支持

Spring Data官方网址:https://spring.io/projects/spring-data/

Spring Data 常用的功能模块如下:

  • Spring Data JDBC
  • Spring Data JPA
  • Spring Data LDAP
  • Spring Data MongoDB
  • Spring Data Redis
  • Spring Data R2DBC
  • Spring Data REST
  • Spring Data for Apache Cassandra
  • Spring Data for Apache Geode
  • Spring Data for Apache Solr
  • Spring Data for Pivotal GemFire
  • Spring Data Couchbase
  • Spring Data Elasticsearch
  • Spring Data Envers
  • Spring Data Neo4j
  • Spring Data JDBC Extensions
  • Spring for Apache Hadoop

SpringData 与 MyBatis 对比:
Spring Data:它不是一个单一的持久层框架,而是一个项目系列,提供了对多种数据存储的支持,包括关系型数据库(如JPA、JDBC)、NoSQL数据库(如MongoDB、Redis、Cassandra等)以及其他数据源。Spring Data 通过提供一致的编程模型和约定,简化了数据访问层的开发。
MyBatis:它是一个基于Java的持久层框架,允许开发者自定义SQL语句、存储过程和高级映射。MyBatis 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集,它使用XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Objects)为数据库中的记录。

SpringData集成示例Gitee地址: https://gitee.com/dreamPointer/dreampointer.git,在demo-elasticsearch下

4. 第四章 SparkStreaming集成ES

Spark Streaming 是Spark core API的扩展,大数据分析引擎,支持实时数据流的处理,并且具有可扩展,高吞吐量,容错的特点。数据可以从许多来源获取,如Kafka, Flume,Kinesis或TCP sockets,并且可以使用复杂的算法进行处理,这些算法使用诸如 map,reduce,join和 window等高级函数表示。最后,处理后的数据可以推送到文件系统,数据库等。实际上,您可以将Spark的机器学习和图形处理算法应用于数据流。

一、创建Maven项目。安装 2.12.11 版本Scala SDK

二、修改 pom 文件,添加Spark相关依赖。

<dependencies><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-streaming_2.12</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</version></dependency><!-- elasticsearch 的客户端 --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.8.0</version></dependency><!-- elasticsearch 依赖 2.x 的 log4j --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.8.2</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.8.2</version></dependency>
</dependencies>

三、功能实现

import org.apache.http.HttpHost
import org.apache.spark.SparkConf
import org.apache.spark.streaming.dstream.ReceiverInputDStream
import org.apache.spark.streaming.Seconds
import org.apache.spark.streaming.StreamingContext
import org.elasticsearch.action.index.IndexRequest
import org.elasticsearch.client.{RequestOptions, RestClient, RestHighLevelClient}
import org.elasticsearch.common.xcontent.XContentType
import java.util.Dateobject SparkStreamingESTest {private val hostIp = "localhost"private val port = 9200private val protocol = "http"private val esClient = new RestHighLevelClient(RestClient.builder(new HttpHost(hostIp, port, protocol)));// 应用程序的主函数def main(args: Array[String]): Unit = {// 创建一个 Spark 配置对象,设置运行模式和应用程序名称val sparkConf = new SparkConf().setMaster("local[*]").setAppName("SparkStreamingESTest")// 使用 Spark 配置对象和批处理间隔(3秒)创建一个 StreamingContext 对象val streamContext = new StreamingContext(sparkConf, Seconds(3))// 根据指定主机端口创建 ReceiverInputDStream 对象,用于接收 socket 流数据val stream: ReceiverInputDStream[String] = streamContext.socketTextStream("localhost", 9999)// 遍历每个 RDD(即每个批处理的数据)stream.foreachRDD(rdd => {println("================" + new Date() + "================") // 每3秒循环一次// 遍历 RDD 中的每个元素(即每条接收到的数据)rdd.foreach(data => {// 根据空格分割数据,并设置索引名称和文档的唯一标识val ss = data.split(" ")println("ss = " + ss.mkString(","))// 构造一个包含数据的JSON字符串val productJson =s"""| { "data":"${ss(1)}" }|""".stripMargin;// 创建 IndexRequest 对象val request = new IndexRequest().index("sparkstreaming").id(ss(0)).source(productJson, XContentType.JSON) // 添加文档数据,数据格式为 JSON// 向 ES 发送请求,获取响应对象val response = esClient.index(request, RequestOptions.DEFAULT);// 打印响应结果System.out.println("_index:" + response.getIndex());System.out.println("_id:" + response.getId());System.out.println("_result:" + response.getResult());})})// 添加 JVM 关闭钩子,停止时关闭 ES 客户端Runtime.getRuntime.addShutdownHook(new Thread() {override def run(): Unit = {closeClient(esClient)}})streamContext.start()streamContext.awaitTermination()}// 关闭 ES 客户端private def closeClient(client: RestHighLevelClient): Unit = {try {if (client != null) {client.close()}} catch {case e: Exception =>e.printStackTrace()}}
}

四、测试

  1. 输入 nc -l 9999 命令连接 9999 端口(nc也称为netcat,是一个功能强大的网络工具,用于在TCP或UDP协议上读取和写入数据)
  2. 输入“1100 ziang-test”,回车发送数据
  3. curl http://localhost:9200/sparkstreaming/_doc/1100,查询ES是否存在该数据

5. 第五章 Flink集成ES

Apache Spark是一-种基于内存的快速、通用、可扩展的大数据分析计算引擎。Apache Spark掀开了内存计算的先河,以内存作为赌注,贏得了内存计算的飞速发展。但是在其火热的同时,开发人员发现,在Spark中,计算框架普遍存在的缺点和不足依然没有完全解决,而这些问题随着5G时代的来临以及决策者对实时数据分析结果的迫切需要而凸显的更加明显:

  • 乱序数据,迟到数据
  • 低延迟,高吞吐,准确性
  • 容错性
  • 数据精准一次性处理(Exactly-Once)

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。在Spark火热的同时,也默默地发展自己,并尝试着解决其他计算框架的问题。慢慢地,随着这些问题的解决,Flink 慢慢被绝大数程序员所熟知并进行大力推广,阿里公司在2015年改进Flink,并创建了内部分支Blink,目前服务于阿里集团内部搜索、推荐、广告和蚂蚁等大量核心实时业务。

一、创建Maven项目。

二、修改 pom 文件,增加相关依赖类库。

<dependencies><dependency><groupId>org.apache.flink</groupId><artifactId>flink-scala_2.12</artifactId><version>1.12.0</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-streaming-scala_2.12</artifactId><version>1.12.0</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-clients_2.12</artifactId><version>1.12.0</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-elasticsearch7_2.11</artifactId><version>1.12.0</version></dependency><!-- jackson --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.11.1</version></dependency>
</dependencies>

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

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

相关文章

Vue Router进阶详解

导航守卫 若依框架登录鉴权详解&#xff08;动态路由&#xff09;_若依鉴权-CSDN博客 完整的导航解析流程 导航被触发&#xff1a; 当用户点击页面中的链接、使用编程式导航&#xff08;如router.push或router.replace&#xff09;或手动输入URL时&#xff0c;导航流程被触发。…

力扣排序242题 有效的子母异位词

题目&#xff1a; 242.有效的字母异位词 给定两个字符串s和t &#xff0c;编写一个函数来判断 t是否是s的字母异位词。 示例1: 输入: s "anagram", t "nagaram" 输出: true 解题思路&#xff1a; 要判断两个字符串s和t是否为子母异位词&#xff0c;也…

html简易流程图

效果图 使用htmlcssjs&#xff0c;无图片&#xff0c;没用Canvas demo: <!DOCTYPE html> <html> <head><link href"draw.css" rel"stylesheet" /><script src"draw.js" type"text/javascript"></…

51单片机教程(一)- 开发环境搭建

1、开发环境搭建 1 环境准备 1 单片机介绍 单片机&#xff08;Single-Chip Microcomputer&#xff0c;简称MCU&#xff09;是一种集成电路芯片&#xff0c;是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第3天,分析项目结构

24.11.02 1.分析项目初始结构 IDEA有2种查看Android项目模式&#xff0c;一种是原始的projects模式&#xff0c;重点介绍这个模式下的项目结构 Android模式下的项目结构 这个是经过Android处理后的&#xff0c;并不是真正的项目结构&#xff0c;但是看着很简洁 projects模式…

chrome编辑替换js文件的图文教程

一、找到要修改替换的js文件 二、将文件保存到本地 三、在本地新建一个文件 路径最好跟你要替换的文件的路径保持一致&#xff0c; 四、选中js文件替换 回到原文件右击选择保存并覆盖 点击完保存并覆盖之后回到替换的新文件中&#xff0c;在自动生成的webpack文件中对文件进…

大学城水电管理:Spring Boot应用案例

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理大学城水电管理系统的相关信息成为必然。开…

硅谷15菜单权限

菜单权限 15.1 路由的拆分 15.1.1 路由分析 菜单的权限: 超级管理员账号:admin atguigu123 拥有全部的菜单、按钮的权限 飞行员账号 硅谷333 111111 不包含权限管理模块、按钮的权限并非全部按钮 同一个项目&#xff1a;不同人(职位是不一样的,他能访问到的菜单、…

3D Gaussian Splatting代码详解(二):模型构建

3 模型构建 gaussians GaussianModel(dataset.sh_degree) 3.1 初始化函数 __init__ 构造函数 构造函数 __init__ 的主要作用是初始化 3D 高斯模型的各项参数和激活函数&#xff0c;用于生成 3D 空间中的高斯表示。 初始化球谐函数的参数&#xff1a; self.active_sh_degre…

初知C++:继承

文章目录 1. 继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承基类成员访问方式的变化 2.基类和派生类间的转换3. 继承中的作用域3.1 隐藏规则3.2 考察继承作用域相关选择题 4. 派生类的默认成员函数4.1 4个常见默认成员函数4.2实现一个不能被继承的类 5. …

Java实战项目-基于 SpringBoot+Vue 的医院管理系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

二分,CF 2036 G - Library of Magic

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 G - Library of Magic 二、解题报告 1、思路分析 首先 query(1, n) a ^…

【测试平台】打包 子节点ios环境配置

主要记录如何配置ios打包机环境&#xff0c;ios环境相对来说比较简单的&#xff0c;研发配置好证书可以本地打包&#xff0c;接入流程比较简单了。 打包机系统升级 1.升级mac OS系统 一般升级好几个小时&#xff0c;可以晚上下载好 2.下载xcode并安装 Appstroe 下载安装xco…

矩阵的奇异值分解SVD

为了论述矩阵的奇异值与奇异值分解!需要下面的结论!

parted 磁盘分区

目录 磁盘格式磁盘分区文件系统挂载使用扩展 - parted、fdisk、gdisk 区别 磁盘格式 parted /dev/vdcmklabel gpt # 设置磁盘格式为GPT p # 打印磁盘信息此时磁盘格式设置完成&#xff01; 磁盘分区 开始分区&#xff1a; mkpart data_mysql # 分区名&…

【Linux】权限管理

目录 一、shell&#xff1a; 二、权限&#xff1a; 1、用户理解&#xff1a; 2、文件权限&#xff1a; 3、目录权限&#xff1a; 4、权限掩码&#xff1a; 5、粘滞位&#xff1a; 一、shell&#xff1a; Linux操作系统不仅仅是指Linux内核&#xff0c;而是指基于Linux内核…

【C++ | 数据结构】八大常用排序算法详解

1. 排序的稳定性 排序是我们生活中经常会面对的问题&#xff0c;小朋友站队的时候会按照从矮到高的顺序排列&#xff1b;老师查看上课出勤情况时&#xff0c;会按照学生的学号点名&#xff1b;高考录取时&#xff0c;会按照成绩总分降序依次录取等等。那么对于排序它是如何定义…

PG数据库 jsonb字段 模糊查询

背景&#xff1a; 项目由于多语言的设计&#xff0c;将字段设置成json字段类型&#xff0c;同时存储中文和英文 页面上通过输入框实现模糊的查询 一、表结构&#xff1a;name字段设置jsonb类型 二、表数据 3、Mybatis编写sql select pp.name ->>zh-CN as pmsProductNam…

webpack使用详解

摘要&#xff1a;webpack作为一款主流的构建工具&#xff0c;对比后来者Vite虽然存在一些缺点&#xff0c;例如启动慢&#xff0c;配置复杂等。在很多项目中使用依然基于webpack构建&#xff0c;有必要掌握其概念、构建流程和配置方法。 1 webpack概述 1.1 基本概念 webpack …

【flutter列表播放器】

视频播放器类 import package:jade/configs/PathConfig.dart; import package:jade/utils/Utils.dart; import package:model/user_share/reward_pool_model.dart; import package:pages/user_share/view/user_share_article_detail_page.dart; import package:util/navigato…