首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

从零开始学习 YoMo 系列教程:开篇

YoMo 是什么? YoMo 一套开源的实时边缘计算网关、开发框架和微服务平台,YoMo 关注在工业互联网领域,目的是打造国产化自主可控的实时边缘计算体系。YoMo 目前已在工业互联网领域被部署应用。 Features 通讯层基于QUIC协议,更好地释放了未来 5G 等低时延网络的价值。 为流式处理 (streaming computing) 设计的编解码器​YoMo-Codec Y3​ 大幅度地提升了计算服务的吞吐量。Y3 编解码器经测试比 JSON 解析速度快 10 倍,且 CPU 消耗更低。 基于插件/yomo-plugin的开发模式,上线实时边缘计算处理系统变得更加方便快捷。 白话版 ​yomo-edge​: 接收设备数据,并按照配置,依次执行各个​yomo-plugin​。 ​yomo-codec​: ​yomo-edge​ 向下游传递数据所使用的一种编码方式,有效解决了需要针对不同类型的数据进行分别处理这一问题。 ​yomo-plugin​: 接收和处理从 edge 端发来的数据,并将处理过的数据向下游传递,处理方式可以有很多种:echo-plugin将接收到的数据转换成 string 的形式,并在结尾添加内容;thermometer-plugin将温湿度数据按顺序标上 thermometer id,并将数据保存到时序数据库 influxdb 中。 关于这篇教程 这篇教程总共分为 6 个部分: Part 0 - 开篇 简单介绍一下 YoMo 和这篇教程 Part 1 - Hello World 各种 setup 通过 echo-plugin 熟悉一下如何定义 yomo-plugin yomo-plugin 的作用 一个完整的项目由哪些部分组成 Part 2 - 接收器/Receiver receiver 本身 workflow 的配置 runtime MQTT broker Part 3 - 插件/Plugin 复习一下如何定义 yomo-plugin thermometer-plugin 的作用 配置和运行 Part 4 - 数据展示/Data Visualization influxdb 和 grafana 的配置 使用数据模拟器 在 grafana 中添加 data source 在grafana Part 5 - 硬件 采购 配置 传感器和 IoT Gateway 相关链接 官网:https://yomo.run/ github:http//github.com/yomorun/yomo gitee:https://gitee.com/yomorun/yomo

优秀的个人博客,低调大师

ES7学习笔记(十)聚合查询

聚合查询,它是在搜索的结果上,提供的一些聚合数据信息的方法。比如:求和、最大值、平均数等。聚合查询的类型有很多种,每一种类型都有它自己的目的和输出。在ES中,也有很多种聚合查询,下面我们看看聚合查询的语法结构, "aggregations" : { "<aggregation_name>" : { "<aggregation_type>" : { <aggregation_body> } [,"meta" : { [<meta_data_body>] } ]? [,"aggregations" : { [<sub_aggregation>]+ } ]? } [,"<aggregation_name_2>" : { ... } ]* } aggregations实体包含了所有的聚合查询,如果是多个聚合查询可以用数组,如果只有一个聚合查询使用对象,aggregations也可以简写为aggs。aggregations里边的每一个聚合查询都有一个逻辑名称,这个名称是用户自定义的,在我们的语法结构中,对应的是<aggregation_name>。比如我们的聚合查询要计算平均价格,这时我们自定义的聚合查询的名字就可以叫做avg_price,这个名字要在聚合查询中保持唯一。 在自定义的聚合查询对象中,需要指定聚合查询的类型,这个类型字段往往是对象中的第一个字段,在上面的语法结构中,对应的是<aggregation_type>。在聚合查询的内部,还可以有子聚合查询,对应的是aggregations,但是只有Bucketing 类型的聚合查询才可以有子聚合查询。 metrics 聚合查询 metrics 我觉得在这里翻译成“指标”比较好,也不是太准确,我们还是用英文比较好。metrics 聚合查询的值都是从查询结果中的某一个字段(field)提炼出来的,下面我们就看看一些常用的metrics 聚合查询。我们有如下的一些索引数据,大家先看一下, 索引的名字叫做bank,一些关键的字段有account_number银行账号,balance账户余额,firstname和lastname等,大家可以直接看出它们代表的含义。假如我们想看看银行里所有人的平均余额是多少,那么查询的语句该怎么写呢? POST /bank/_search { "query": { "bool": { "must": { "match_all": {} } } }, "aggs": { "avg_balance": { "avg": { "field": "balance" } } } } 在查询语句中,查询的条件匹配的是全部,在聚合查询中,我们自定义了一个avg_balance的聚合查询,它的类型是avg,求平均数,然后我们指定字段是balance,也就是我们要计算平均数的字段。我们执行一下,然后看看返回的结果, { "took": 11, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": …… "aggregations": { "avg_balance": { "value": 25714.837 } } } 在返回的结果中,我们看到在aggregations中,返回了我们自定义的聚合查询avg_balance,并且计算的平均值是25714.837。 如果我们要查询balance的最大、最小、平均、求和、数量等,可以使用stats查询,我们来看一下如何发送这个请求, POST /bank/_search { "query": { "bool": { "must": { "match_all": {} } } }, "aggs": { "stats_balance": { "stats": { "field": "balance" } } } } 我们只需要把前面聚合查询的类型改为stats就可以了,我们看一下返回的结果, { "took": 20, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": …… "aggregations": { "stats_balance": { "count": 1000, "min": 1011, "max": 49989, "avg": 25714.837, "sum": 25714837 } } } 我们可以看到在返回的结果中,返回了5个字段,我们最常用的最大、最小、平均、求和、数量都包含在内,很方便是不是。 Bucket 聚合查询 Bucket 聚合不像metrics 那样基于某一个值去计算,每一个Bucket (桶)是按照我们定义的准则去判断数据是否会落入桶(bucket)中。一个单独的响应中,bucket(桶)的最大个数默认是10000,我们可以通过serarch.max_buckets去进行调整。 如果从定义来看,理解Bucket聚合查询还是比较难的,而且Bucket聚合查询的种类也有很多,给大家一一介绍不太可能,我们举两个实际中用的比较多的例子吧。在上面的metrics 聚合中,我们可以查询到数量(count),但是我们能不能分组呢?是不是和数据库中的group by联系起来了?对,Bucket 聚合查询就像是数据库中的group by,我们还用上面银行的索引,比如说我们要看各个年龄段的存款人数,那么查询语句我们该怎么写呢?这里就要使用Bucket 聚合中的Terms聚合查询,查询语句如下: POST /bank/_search { "query": { "bool": { "must": { "match_all": {} } } }, "aggs": { "ages": { "terms": { "field": "age" } } } } 其中,ages是我们定义的聚合查询的名称,terms指定要分组的列,我们运行一下,看看结果, …… { "aggregations": { "ages": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 463, "buckets": [ { "key": 31, "doc_count": 61 } , { "key": 39, "doc_count": 60 } , { "key": 26, "doc_count": 59 } , { "key": 32, "doc_count": 52 } , { "key": 35, "doc_count": 52 } , { "key": 36, "doc_count": 52 } , { "key": 22, "doc_count": 51 } , { "key": 28, "doc_count": 51 } , { "key": 33, "doc_count": 50 } , { "key": 34, "doc_count": 49 } ] } } 我们可以看到在返回的结果中,每个年龄的数据都汇总出来了。假如我们要看每个年龄段的存款余额,该怎么办呢?这里就要用到子聚合查询了,在Bucket 聚合中,再加入子聚合查询了,我们看看怎么写, POST /bank/_search { "query": { "bool": { "must": { "match_all": {} } } }, "aggs": { "ages": { "terms": { "field": "age" }, "aggs": { "sum_balance": { "sum": { "field": "balance" } } } } } } 我们在聚合类型terms的后面又加了子聚合查询,在子聚合查询中,又自定义了一个sum_balance的查询,它是一个metrics 聚合查询,要对字段balance进行求和。我们运行一下,看看结果。 "aggregations": { "ages": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 463, "buckets": [ { "key": 31, "doc_count": 61, "sum_balance": { "value": 1727088 } } , { "key": 39, "doc_count": 60, "sum_balance": { "value": 1516175 } } , { "key": 26, "doc_count": 59, "sum_balance": { "value": 1368494 } } , { "key": 32, "doc_count": 52, "sum_balance": { "value": 1245470 } } , { "key": 35, "doc_count": 52, "sum_balance": { "value": 1151108 } } , { "key": 36, "doc_count": 52, "sum_balance": { "value": 1153085 } } , { "key": 22, "doc_count": 51, "sum_balance": { "value": 1261285 } } , { "key": 28, "doc_count": 51, "sum_balance": { "value": 1441968 } } , { "key": 33, "doc_count": 50, "sum_balance": { "value": 1254697 } } , { "key": 34, "doc_count": 49, "sum_balance": { "value": 1313688 } } ] } } 我们看到返回结果中,增加了我们定义的sum_balance字段,它是balance余额的汇总。这个例子我们应该对bucket(桶)这个概念有了一个非常形象的认识了。还有一些其他的bucket聚合查询,这里就不给大家一一介绍了,比如:我们只想查某几个年龄段的余额汇总,就可以使用filters-aggregation。 好了,ES的一些基本的聚合查询就给大家介绍到这里了,如果要用到一些其他的聚合查询,可以参照ES的官方文档。

优秀的个人博客,低调大师

ES[7.6.x]学习笔记(九)搜索

搜索是ES最最核心的内容,没有之一。前面章节的内容,索引、动态映射、分词器等都是铺垫,最重要的就是最后点击搜索这一下。下面我们就看看点击搜索这一下的背后,都做了哪些事情。 分数(score) ES的搜索结果是按照相关分数的高低进行排序的,咦?! 怎么没说搜索先说搜索结果的排序了?咱们这里先把这个概念提出来,因为在搜索的过程中,会计算这个分数。这个分数代表了这条记录匹配搜索内容的相关程度。分数是一个浮点型的数字,对应的是搜索结果中的_score字段,分数越高代表匹配度越高,排序越靠前。 在ES的搜索当中,分为两种,一种计算分数,而另外一种是不计算分数的。 查询(query context) 查询,代表的是这条记录与搜索内容匹配的怎么样,除了决定这条记录是否匹配外,还要计算这条记录的相关分数。这个和咱们平时的查询是一样的,比如我们搜索一个关键词,分词以后匹配到相关的记录,这些相关的记录都是查询的结果,那这些结果谁排名靠前,谁排名靠后呢?这个就要看匹配的程度,也就是计算的分数。 过滤(filter context) 过滤,代表的含义非常的简单,就是YES or NO,这条记录是否匹配查询条件,它不会计算分数。频繁使用的过滤还会被ES加入到缓存,以提升ES的性能。下面我们看一个查询和过滤的例子,这个也是ES官网中的例子。 GET /_search { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "filter": [ { "term": { "status": "published" }}, { "range": { "publish_date": { "gte": "2015-01-01" }}} ] } } } 我们看一下请求的路径/_search,这个是请求的路径,而请求的方法是GET,我们再看请求体中,有一个query,这个代表着查询的条件。而bool中的must被用作query context,它在查询的时候会计算记录匹配的相关分数。filter中的条件用作过滤,只会把符合条件的记录检索出来,不会计算分数。 组合查询 组合查询包含了其他的查询,像我们前面提到的query context和filter context。在组合查询中,分为很多种类型,我们挑重点的类型给大家介绍一下。 Boolean Query boolean查询,前面我们写的查询语句就是一个boolean查询,boolean查询中有几个关键词,表格如下: 关键词 描述 must 必须满足的条件,而且会计算分数, filter 必须满足的条件,不会计算分数 should 可以满足的条件,会计算分数 must_not 必须不满足的条件,不会计算分数 我们看看下面的查询语句: POST _search { "query": { "bool" : { "must" : { "term" : { "user" : "kimchy" } }, "filter": { "term" : { "tag" : "tech" } }, "must_not" : { "range" : { "age" : { "gte" : 10, "lte" : 20 } } }, "should" : [ { "term" : { "tag" : "wow" } }, { "term" : { "tag" : "elasticsearch" } } ], "minimum_should_match" : 1, "boost" : 1.0 } } } 上面的查询是一个典型的boolean组合查询,里边的关键词都用上了。很多小伙伴们可能对must和should的区别不是很了解,must是必须满足的条件,我们的例子中must里只写了一个条件,如果是多个条件,那么里边的所有条件必须满足。而should就不一样了,should里边现在列出了两个条件,并不是说这两个条件必须满足,到底需要满足几个呢?我们看一下下面的关键字minimum_should_match,从字面上我们就可以看出它的含义,最小should匹配数,在这里设置的是1,也就是说,should里的条件只要满足1个,就算匹配成功。在boolean查询中,如果存在一个should条件,而没有filter和must条件的话,那么minimum_should_match的默认值是1,其他情况默认值是0。 我们再看一个实际的例子吧,还记得前面我们创建的ik_index索引吗?索引中存在着几条数据,数据如下: _index _type _id ▲_score id title desc ik_index _doc fEsN-HEBZl0Dh1ayKWZb 1 1 苹果 苹果真好吃 ik_index _doc 2 1 1 香蕉 香蕉真好吃 ik_index _doc 1 1 1 香蕉 香蕉真好吃 ik_index _doc 3 1 1 橘子 橘子真好吃 ik_index _doc 4 1 1 桃子 桃子真好吃 只有5条记录,我们新建一个查询语句,如下: POST /ik_index/_search { "query":{ "bool":{ "must":[ { "match":{ "desc":"香蕉好吃" } } ] } }, "from":0, "size":10, } 我们查询的条件是desc字段满足香蕉好吃,由于我们使用的ik分词器,查询条件香蕉好吃会被分词为香蕉和好吃,但是5的数据的desc中都有好吃字段,所有5条数据都会被查询出来,我们执行一下,看看结果: _index _type _id ▲_score id title desc ik_index _doc 2 0.98773474 1 香蕉 香蕉真好吃 ik_index _doc 1 0.98773474 1 香蕉 香蕉真好吃 ik_index _doc 3 0.08929447 1 橘子 橘子真好吃 ik_index _doc 4 0.08929447 1 桃子 桃子真好吃 ik_index _doc fEsN-HEBZl0Dh1ayKWZb 0.07893815 1 苹果 苹果真好吃 哈哈,5条数据全部查询出来了,和我们的预期是一样的,但是,我们需要注意一点的是_score字段,它们的分数是不一样的,我们的查询条件是香蕉好吃,所以既包含香蕉又包含好吃的数据分数高,我们看到分数到了0.98,而另外3条数据只匹配了好吃,所以分数只有0.7,0.8。 Boosting Query 这个查询比较有意思,它有两个关键词positive和negative,positive是“正”,所有满足positive条件的数据都会被查询出来,negative是“负”,满足negative条件的数据并不会被过滤掉,而是会扣减分数。那么扣减分数要扣减多少呢?这里边有另外一个字段negative_boost,这个字段是得分的系数,它的分数在0~1之间,满足了negative条件的数据,它们的分数会乘以这个系数,比如这个系数是0.5,原来100分的数据如果满足了negative条件,它的分数会乘以0.5,变成50分。我们看看下面的例子, POST /ik_index/_search { "query": { "boosting": { "positive": { "term": { "desc": "好吃" } }, "negative": { "term": { "desc": "香蕉" } }, "negative_boost": 0.5 } } } positive条件是好吃,只要desc中有“好吃”的数据都会被查询出来,而negative的条件是香蕉,只要desc中包含“香蕉”的数据都会被扣减分数,扣减多少分数呢?它的得分将会变为原分数*0.5。我们执行一下,看看效果, index type _id score _source.id source.title source.desc ik_index _doc 3 0.08929447 1 橘子 橘子真好吃 ik_index _doc 4 0.08929447 1 桃子 桃子真好吃 ik_index _doc fEsN-HEBZl0Dh1ayKWZb 0.07893815 1 苹果 苹果真好吃 ik_index _doc 2 0.044647235 1 香蕉 香蕉真好吃 ik_index _doc 1 0.044647235 1 香蕉 香蕉真好吃 我们可以看到前3条数据的分数都在0.09左右,而后两条的数据在0.044左右,很显然,后两条数据中的desc包含香蕉,它们的得分会乘以0.5的系数,所以分数只有前面数据的分数的一半。 全文检索 在前面几节的内容中,我们介绍过,只有字段的类型是text,才会使用全文检索,全文检索会使用到分析器,在我们的ik_index索引中,title和desc字段都是text类型,所以,这两个字段的搜索都会使用到ik中文分词器。全文检索比起前面的组合检索要简单一点,当然,在ES的官方文档中,全文检索中的内容还是挺多的,在这里我们只介绍一个标准的全文检索。 我们看看下面的语句, POST /ik_index/_search { "query": { "match": { "desc": { "query": "苹果" } } } } 在请求体中,match代替了之前的bool,match是标准的全文索引的查询。match后面跟的字段是要查询的字段名,在咱们的例子中,查询的字段是desc,如果有多个字段,可以列举多个。desc字段里,query就是要查询的内容。我们还可以在字段中指定分析器,使用analyzer关键字,如果不指定,默认就是索引的分析器。我们执行一下上面的查询,结果如下: index type _id score source.id source.title source.desc ik_index _doc fEsN-HEBZl0Dh1ayKWZb 1.2576691 1 苹果 苹果真好吃 我们可以看到相应的数据已经检索出来了。 最后 在ES中,检索的花样是比较多的,这里也不能一一给大家介绍了,只介绍一些最基本、最常用的查询功能。下一篇我们看一下ES的聚合查询功能。

优秀的个人博客,低调大师

ES7学习笔记(五)动态映射

通常情况下,我们使用ES建立索引的步骤是,先创建索引,然后定义索引中的字段以及映射的类型,然后再向索引中导入数据。而动态映射是ES中一个非常重要的概念,你可以直接向文档中导入一条数据,与此同时,索引、字段、字段类型都会自动创建,无需你做其他的操作。这就是动态映射的神奇之处。 动态字段映射 ES的动态映射默认是开启的,动态映射的默认规则如下: JSON的数据类型 ES中的数据类型 null 不会映射字段 true 或 false boolean类型 浮点型数字 float 整型数字 long JSON对象 Object 数组 第一个非空值得类型 String 1、如果满足日期类型的格式,映射为日期类型 2、如果满足数字型的格式,映射为long或者float 3、如果就是字符串,会映射为一个text类型和一个keyword类型 接下来我们看看动态映射的一个例子,我们直接向dynamic-index索引中存放一条数据,注意,dynamic-index这个索引我们没有创建过,直接存放数据,索引会自动创建。接下来,我们看一下具体的请求: PUT /dynamic-index/_doc/1 { "my_null": null, "my_boolean": false, "my_float": 1.56, "my_long": 3, "my_object": { "my_first": "first value", "my_second": "second_value" }, "my_array": [1,2,3], "my_date_1": "2020-05-01", "my_date_2": "2020/05/01 12:03:03", "my_date_3": "05/01/2020", "my_string_long": "1", "my_string_float": "4.6", "my_string": "中华人民共和国" } 请求执行成功以后,我们先看一下索引的类型: GET /dynamic-index/_mapping 返回的结果如下: { "dynamic-index": { "mappings": { "properties": { "my_array": { "type": "long" }, "my_boolean": { "type": "boolean" }, "my_date_1": { "type": "date" }, "my_date_2": { "type": "date", "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" }, "my_date_3": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_float": { "type": "float" }, "my_long": { "type": "long" }, "my_object": { "properties": { "my_first": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_second": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, "my_string": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_string_float": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_string_long": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } 返回的结果比较长,我们把每一个字段都看一下,看看动态映射的字段是否达到了我们的预期: 字段 映射结果 是否达到预期 原因 my_null 没有映射 是 null值不映射 my_boolean boolean 是 my_float float 是 my_long long 是 my_object object 是 my_object里自动生成了两个字段的映射 my_array long 是 数组中的数字是long型 my_date_1 date 是 my_date_2 date 是 my_date_3 text 否 没有指定这种日期格式,所以映射为text my_string_long text 否 数字探测默认关闭,没有打开 my_string_float text 否 数字探测默认关闭,没有打开 my_string text 是 普通字符串,映射为text 下面我们把数字探测打开,执行如下请求: PUT /dynamic-index { "mappings": { "numeric_detection": true } } 由于我们的索引dynamic-index中,存在了映射关系,再进行设置是会报错的,所以我们要将索引删除,执行如下请求: DELETE /dynamic-index 索引删除成功后,再执行前面的设置,执行成功,数字探测已经打开。然后再添加一种日期格式MM/dd/yyyy,请求如下: PUT /dynamic-index { "mappings": { "dynamic_date_formats": ["MM/dd/yyyy"] } } 执行报错,错误信息和之前一样,看来日期的设置要和数字探测一起才行,我们再将索引删除,然后再发送请求,两个设置一起: PUT /dynamic-index { "mappings": { "numeric_detection": true, "dynamic_date_formats": ["MM/dd/yyyy"] } } 执行成功,我们再发送之前创建索引数据的请求 PUT /dynamic-index/_doc/1 { "my_null": null, "my_boolean": false, "my_float": 1.56, "my_long": 3, "my_object": { "my_first": "first value", "my_second": "second_value" }, "my_array": [1,2,3], "my_date_1": "2020-05-01", "my_date_2": "2020/05/01 12:03:03", "my_date_3": "05/01/2020", "my_string_long": "1", "my_string_float": "4.6", "my_string": "中华人民共和国" } 执行成功,我们再看一下索引的映射, "my_string_float": { "type": "float" }, "my_string_long": { "type": "long" } "my_date_1": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_date_2": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "my_date_3": { "type": "date", "format": "MM/dd/yyyy" }, 我们重点看一下以上几个字段,my_string_float和my_string_long映射成我们想要的类型了,由于我们开启了数字探测。再看看我们映射的3个日期类型,咦?只有my_date_3映射了日期类型,其他两个都是映射成了text类型,这是由于我们在设置dynamic_date_formats时,只指定了一种格式。我们只需要把其他两种类型的日期格式也加上就可以了。 { "mappings": { "numeric_detection": true, "dynamic_date_formats": ["MM/dd/yyyy","yyyy/MM/dd HH:mm:ss","yyyy-MM-dd"] } } 这里就不给大家具体演示了,有兴趣的小伙伴去尝试一下把。 动态字段是ES中一个非常重要的功能,它给我们带来了极大的方便,也省去了我们在开发时创建索引字段的时间,真是事半功倍,小伙伴们要好好掌握哦~~

优秀的个人博客,低调大师

ES7学习笔记(三)新建索引

与ES的交互方式 与es的交互方式采用http的请求方式,请求的格式如下: curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>' 是请求的方法,比如:GET、POST、DELETE、PUT等。 协议:http或者https。 主机地址。 端口 API的路径。比如查看集群状态:/_cluster/stats。 参数。比如:?pretty,打印出格式化以后的Json。 请求的内容。比如:添加索引时的数据。 创建索引 es创建索引的请求方式如下: PUT /<index> 请求的方法用PUT。 /后面直接跟索引的名称即可。 索引的设置和字段都放在Body中。 比如我们创建一个名字叫组织机构的索引,这个索引只有两个字段,一个id,一个name。并且这个索引设置为2个分片,2个副本。 我们使用POSTMAN发送请求,如下: http://192.168.73.130:9200/orgnization 请求的方法选择PUT。然后在请求体(Body)中,写上索引的字段名称,索引的分片数和副本数,如下: { "settings":{ "number_of_shards":2, "number_of_replicas":2 }, "mappings":{ "properties":{ "id":{ "type":"long" }, "name":{ "type":"text" } } } } 我们观察一下,请求体中分为两个部分:settings和mappings。在settings中,我们设置了分片数和副本数。 number_of_shards:分片的数量; number_of_replicas:副本的数量; 在mappings中,我们设置索引的字段,在这里,我们只设置了id和name,id的映射类型是long,name的映射类型是text。这些类型我们会在后续为大家介绍。 请求体写完后,我们点击发送,es返回的结果如下: { "acknowledged": true, "shards_acknowledged": true, "index": "orgnization" } 说明索引创建成功,索引的名字正是我们在请求中设置的orgnization。 然后,我们通过elasticsearch-head插件观察一下刚才创建的索引,如图: 我们可以看到索引orgnization已经创建好了,它有2个分片,分别是0和1,并且每个分片都是两个副本。如果我们仔细观察这个图,可以看出node-130节点中的0分片,和node-132节点中的1分片,它们的边框是加粗的,这说明它们是主节点,而边框没有加粗的节点是从节点,也就是我们说的副本节点。 查看索引 如果我们要查看一个索引的设置,可以通过如下请求方式: GET /<index> 在我们的例子中,查看orgnization索引的设置,我们在POSTMAN中发送如下的请求: 我们可以看到索引的具体设置,比如:mapping的设置,分片和副本的设置。这些和我们创建索引时候的设置是一样的。 修改索引 索引一旦创建,我们是无法修改里边的内容的,不如说修改索引字段的名称。但是我们是可以向索引中添加其他字段的,添加字段的方式如下: PUT /<index>/_mapping 然后在我们的请求体中,写好新添加的字段。比如,在我们的例子当中,新添加一个type字段,它的类型我们定义为long,请求如下: http://192.168.73.130:9200/orgnization/_mapping 请求类型要改为PUT,请求体如下: { "properties": { "type": { "type": "long" } } } 我们点击发送,返回的结果如图所示: 添加索引字段成功,我们再使用GET查看一下索引,如图: 我们可以成功的查询到新添加的索引字段了。 删除索引 如果我们要删除一个索引,请求方式如下: DELETE /<index> 假如我们要删除刚才创建的orgnization索引,我们只要把请求的方法改成DELETE,然后访问我们索引就可以, http://192.168.73.130:9200/orgnization 关闭索引 如果索引被关闭,那么关于这个索引的所有读写操作都会被阻断。索引的关闭也很简单,请求方式如下: POST /<index>/_close 在我们的例子中,如果要关闭索引,降请求方法改成POST,然后发送如下请求: http://192.168.73.130:9200/orgnization/_close 打开索引 与关闭索引相对应的是打开索引,请求方式如下: POST /<index>/_open 在我们的例子中,如果要打开索引,降请求方法改成POST,然后发送如下请求: http://192.168.73.130:9200/orgnization/_open 冻结索引 冻结索引和关闭索引类似,关闭索引是既不能读,也不能写。而冻结索引是可以读,但是不能写。冻结索引的请求方式如下: POST /<index>/_freeze 对应我们的例子当中: http://192.168.73.130:9200/orgnization/_freeze 解冻索引 与冻结索引对应的是解冻索引,方式如下: POST /<index>/_unfreeze 对应我们的例子: http://192.168.73.130:9200/orgnization/_unfreeze

优秀的个人博客,低调大师

python学习之数据库mariadb操作

数据库简介数据库分类关系型数据库:指采用了关系模型来组织数据的数据库。关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。主流的关系型数据库有:Oracle、Microsoft SQL Server、MySQL、PostgreSQL,SQLite、MariaDB(MySQL的一个分支)Microsoft Access、SAP。非关系型数据库:指非关系型的,分布式的,以键值对存储且结构不固定,可以减少一些时间和空间的开销。非关系型数据库都是针对某些特定的应用需求,主要分为以下几类:1). 面向海量数据访问的面向文档数据库:MongoDB、Amazon DynamoDB、Couchbase等。2). 面向高性能并发读写的key-value数据库: Redis、 Memcached等。3). 面向搜索数据内容的搜索引擎:Elasticsearch,Splunk,Solr,MarkLogic和Sphinx等。4). 面向可扩展性的分布式数据库:Cassandra,HBase等。当前物理的数据库都是按照E-R模型进行设计的,• E表示entry,实体• R表示relationship,关系• 一个实体转换为数据库中的一个表关系描述两个实体之间的对应规则,包括: 一对一 ,一对多, 多对多经过研究和对使用中问题的总结,对于设计数据库提出了一些规范,这些规范被称为范式• 第一范式(1NF):列不可拆分 , 即无重复的域。• 第二范式(2NF):唯一标识 ,即拥有实体的唯一标识(eg: 身份证、id号等)。• 第三范式(3NF):引用主键 ,即每列数据都与主键直接相关。说明:关系型数据库有六种范式。一般说来,数据库只需满足第三范式(3NF)就行了。MySQL常用存储引擎分析数据库存储引擎是数据库底层软件组织,进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能, MySQL的核心就是存储引擎。MySQL查询存储引擎SQL语句:SHOW ENGINES安装数据库服务管理安全性密码设置 关闭mysql服务器的防火墙 用户授权: 允许root用户通过westos密码 在任意主机(%)远程登陆并操作数据库;允许远程连接找回密码数据库操作表操作表创建: 数据完整性• 一个数据库就是一个完整的业务单元,可以包含多张表,数据被存储在表中• 在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证, 包括数据字段的类型、约束在mysql中包含的数据类型很多,这里主要列出来常用的几种:• 数字:int,decimal, float• 字符串:varchar,text• 日期:datetime• 布尔:bool表的创建: 约束• 主键 primary key• 非空 not null• 惟一 unique• 默认 default• 外键 foreign key• 自动增长 auto_increment数据操作备份与恢复查询的基本语法select from 表名;• from关键字后面写表名,表示数据来源于是这张表• select后面写表中的列名,如果是表示在结果中显示表中所有列• 在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中• 如果要查询多个列,之间使用逗号分隔消除重复行在select后面列前使用distinct可以消除重复的行select distinct gender from students;条件使用where子句对表中的数据筛选,结果为true的行会出现在结果集中select * from 表名 where 条件;优先级•小括号,not,比较运算符,逻辑运算符•and比or先运算,如果同时出现并希望先算or,需要结合()使用分组• 按照字段分组,表示此字段相同的数据会被放到一个组中• 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中• 可以对分组后的数据进行统计,做聚合运算select 列1,列2,聚合... from 表名 group by 列1,列2,列3...分组后的数据筛选having后面的条件运算符与where的相同对比where与having• where是对from后面指定的表进行数据筛选,属于对原始数据的筛选• having是对group by的结果进行筛选聚合为了快速得到统计数据,提供了5个聚合函数排序为了方便查看数据,可以对数据进行排序:• 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推• 默认按照列值从小到大排列• asc从小到大排列,即升序, desc从大到小排序,即降序获取部分行当数据量过大时,在一页中查看数据是一件非常麻烦的事情:• 从start开始,获取count条数据• start索引从0开始实验: 客户端可以远程连接服务端数据库 客户端: 172.25.254.197 服务端: 172.25.254.18服务端操作: $ mysql -uroot -p#查看mysql数据库中user数据库表的三列内容: Host,User,Password.MariaDB [(none)]> select Host,User,Password from mysql.user;#172.25.254.197这台主机以root用户身份远程登录, 密码为westos, 访问数据库的所有内容(.)MariaDB [(none)]> grant all on . to root@'172.25.254.197' identified by 'westos';#任意一台主机以root用户身份远程登录, 密码为westos, 访问数据库的所有内容(.)#sql语句中的%等价于.MariaDB [(none)]> grant all on . to root@'%' identified by 'westos';#任意一台主机以root用户身份远程登录, 密码为westos, 访问mysql数据库的所有表(mysql.)MariaDB [(none)]> grant all on mysql.* to root@'%' identified by 'westos';MariaDB [(none)]> select Host,User,Password from mysql.user; #删除用户授权(远程登录)MariaDB [(none)]> drop user root@'%'; 客户端测试: #指定主机名为172.25.254.18, 用户名为root远程登录.$ mysql -h 172.25.254.18 -uroot -pwestos#创建数据库Blog并指定编码格式为utf8(存储的数据为中文, 需要设置);MariaDB [(none)]> create database Blog default charset='utf8';#显示所有数据库名称;MariaDB [(none)]> show databases;#选择/切换数据库Blog;MariaDB [(none)]> use Blog;#查看当前选择的数据库;MariaDB [Blog]> select database();#查看当前数据库的所有数据库表;MariaDB [Blog]> show tables;#创建数据库表userinfo, 两列数据。#varchar可变长字符串, not null数据非空,unique数据唯一。MariaDB [Blog]> create table userinfo(-> username varchar(20) not null unique,-> password varchar(20) not null)-> ;#查看表结构MariaDB [Blog]> desc userinfo;#添加数据到数据表中;MariaDB [Blog]> insert into userinfo values('user2', 'passwd');MariaDB [Blog]> insert into userinfo values('张三', 'passwd');#数据查询;MariaDB [Blog]> select * from userinfo;#修改表结构: 添加一列信息、修改一列信息、删除一列信息.MariaDB [Blog]> alter table userinfo add gender varchar(3);MariaDB [Blog]> alter table userinfo change gender sex varchar(3);MariaDB [Blog]> alter table userinfo drop sex;#数据表重命名;MariaDB [Blog]> rename table userinfo to users;#查看表的常见语句;MariaDB [Blog]> show create table users;#删除数据表;MariaDB [Blog]> drop table users;#删除数据库;MariaDB [Blog]> drop database Blog;MariaDB [(none)]> create database Blog default charset='utf8';MariaDB [(none)]> use Blog;MariaDB [Blog]> create table users(-> id int primary key auto_increment,-> username varchar(20) unique not null,-> password varchar(20) not null default '000000');MariaDB [Blog]> desc users;MariaDB [Blog]> insert into users values(1, 'user1', 'password');MariaDB [Blog]> insert into users(username) values('user2');MariaDB [Blog]> insert into users(username) values('user3'),('user4'), ('user5');MariaDB [Blog]> update users set password='666666' where username='user4'; MariaDB [Blog]> select from users where username='user4';MariaDB [Blog]> select from users;MariaDB [Blog]> delete from users where username='user4';MariaDB [Blog]> select * from users;create table student(sno varchar(12) primary key,sname varchar (10) comment '学生姓名',sex varchar (2) comment '性别',age int,address varchar(50),classno varchar (5));#*****关于查询条件**** 1、 查询students表中的所有记录的sname、ssex和class列。MariaDB [Blog]> select sname,ssex,class from students; 2、 查询教师所有的单位即不重复的Depart列。MariaDB [Blog]> select distinct depart from teachers; 3、 查询students表的所有记录。MariaDB [Blog]> select * from students; 4、 查询scores表中成绩在60到80之间的所有记录。MariaDB [Blog]> select * from scores where degree between 60 and 80; 5、 查询scores表中成绩为85,86或88的记录。MariaDB [Blog]> select from scores where degree=85 or degree=86 or degree=88;MariaDB [Blog]> select from scores where degree in (85,86,88); 6、 查询students表中“95031”班或性别为“女”的同学记录。(作业)select * from students where xxxxxx or xxxxx; *关于排序***7、 以class降序查询students表的所有记录。MariaDB [Blog]> select from students order by class desc;MariaDB [Blog]> select from students order by class;(默认升序) 8、 以cno升序、degree降序查询scores表的所有记录。以cno升序、degree降序: 当cno相同时, 按照degree降序排列。cno degree1 31 22 3MariaDB [Blog]> select * from scores order by cno,degree desc; ****关于聚合函数*****9、 查询“95031”班的学生人数。MariaDB [Blog]> select from students where class='95031';MariaDB [Blog]> select count() from students where class='95031';MariaDB [Blog]> select count(*) as studentCount from students where class='95031'; (最终版) 10、查询‘3-105’号课程的平均分。MariaDB [Blog]> select avg(degree) as avgScore from scores where cno='3-105'; ***关于group by 和having*11、查询scores表中至少有5名学生选修的并以3开头的课程的平均分数。12、查询最低分大于70,最高分小于90的Sno列。 13、查询scores表中的最高分的学生学号和课程号。14、查询所有学生的Sname、Cno和Degree列。15、查询所有学生的Sno、Cname和Degree列。16、查询所有学生的Sname、Cname和Degree列。17、查询“95033”班所选课程的平均分。USE Blog; CREATE TABLE IF NOT EXISTS students(sno VARCHAR(3) NOT NULL, sname VARCHAR(4) NOT NULL,ssex VARCHAR(2) NOT NULL, sbirthday DATETIME,class VARCHAR(5)); CREATE TABLE IF NOT EXISTS courses(cno VARCHAR(5) NOT NULL, cname VARCHAR(10) NOT NULL,tno VARCHAR(10) NOT NULL); CREATE TABLE IF NOT EXISTS scores (sno VARCHAR(3) NOT NULL, cno VARCHAR(5) NOT NULL, degree NUMERIC(10, 1) NOT NULL); CREATE TABLE IF NOT EXISTS teachers (tno VARCHAR(3) NOT NULL, tname VARCHAR(4) NOT NULL, tsex VARCHAR(2) NOT NULL, tbirthday DATETIME NOT NULL, prof VARCHAR(6), depart VARCHAR(10) NOT NULL); INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (108 ,'曾华' ,'男' ,'1977-09-01',95033);INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (105 ,'匡明' ,'男' ,'1975-10-02',95031);INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (107 ,'王丽' ,'女' ,'1976-01-23',95033);INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (101 ,'李军' ,'男' ,'1976-02-20',95033);INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (109 ,'王芳' ,'女' ,'1975-02-10',95031);INSERT INTO students (sno,sname,ssex,sbirthday,class) VALUES (103 ,'陆君' ,'男' ,'1974-06-03',95031); INSERT INTO courses(cno,cname,tno)VALUES ('3-105' ,'计算机导论',825);INSERT INTO courses(cno,cname,tno)VALUES ('3-245' ,'操作系统' ,804);INSERT INTO courses(cno,cname,tno)VALUES ('6-166' ,'数据电路' ,856);INSERT INTO courses(cno,cname,tno)VALUES ('9-888' ,'高等数学' ,100); INSERT INTO scores(sno,cno,degree)VALUES (103,'3-245',86);INSERT INTO scores(sno,cno,degree)VALUES (105,'3-245',75);INSERT INTO scores(sno,cno,degree)VALUES (109,'3-245',68);INSERT INTO scores(sno,cno,degree)VALUES (103,'3-105',92);INSERT INTO scores(sno,cno,degree)VALUES (105,'3-105',88);INSERT INTO scores(sno,cno,degree)VALUES (109,'3-105',76);INSERT INTO scores(sno,cno,degree)VALUES (101,'3-105',64);INSERT INTO scores(sno,cno,degree)VALUES (107,'3-105',91);INSERT INTO scores(sno,cno,degree)VALUES (108,'3-105',78);INSERT INTO scores(sno,cno,degree)VALUES (101,'6-166',85);INSERT INTO scores(sno,cno,degree)VALUES (107,'6-106',79);INSERT INTO scores(sno,cno,degree)VALUES (108,'6-166',81); INSERT INTO teachers(tno,tname,tsex,tbirthday,prof,depart) VALUES (804,'李诚','男','1958-12-02','副教授','计算机系');INSERT INTO teachers(tno,tname,tsex,tbirthday,prof,depart) VALUES (856,'张旭','男','1969-03-12','讲师','电子工程系');INSERT INTO teachers(tno,tname,tsex,tbirthday,prof,depart) VALUES (825,'王萍','女','1972-05-05','助教','计算机系');INSERT INTO teachers(tno,tname,tsex,tbirthday,prof,depart) VALUES (831,'刘冰','女','1977-08-14','助教','电子工程系');

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册