使用Elasticsearch来进行简单的DDL搜索数据

news2024/11/19 10:36:14

说明:Elasticsearch提供了多种多样的搜索方式来满足不同使用场景的需求,我们可以使用Elasticsearch来进行各种复制的查询,进行数据的检索。

1.1 精准查询

用来查询索引中某个类型为keyword的文本字段,类似于SQL的“=”查询。

创建一个test-3-2-1的索引

PUT test-3-2-1
{
  "mappings": {
    "properties": {
      "id": {
        "type": "integer"
      },
      "sex": {
        "type": "boolean"
      },
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "born": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

搜索name为张三的

POST test-3-2-1/_search
{
  "query": {
    "term": {
      "name.keyword": {
        "value": "张三"
      }
    }
  }
}

返回的结果中,took表示搜索耗费的毫秒数,_shards中的total代表本次搜索一共使用了多少个分片,该值一般等于索引主分片数。hits里面的total代表一共搜索到多少结果;max_score代表搜索结果中相关度得分的最大值,默认搜索结果会按照相关度得分降序排列;_score代表单个文档的相关度得分;_source是数据的原始JSON内容。

如果想查询用户名为张三和王五的可以这样写。

POST test-3-2-1/_search
{
  "query": {
    "terms": {
      "name.keyword": [
        "张三",
        "王五"
      ]
    }
  }
}

1.2 范围查询

范围查询也很简单,可以返回某个数值或日期字段处于某一区间的数据。区间筛选参数gt表示大于,gte表示大于等于,lt表示小于,lte表示小于等于。由于索引中保存的时间是UTC时间,以下查询表示查询born日期处于2020/09/1100:00:00(UTC)至2020/09/13 00:00:00(UTC)范围内的数据,可以使用format参数自定义查询的日期格式。

POST test-3-2-1/_search
{
  "query": {
    "range": {
      "born": {
        "gte": "2020/09/11 00:00:00",
        "lte": "2020/09/13 00:00:00",
        "format": "yyyy/MM/dd HH:mm:ss"
      }
    }
  }
}

1.3 存在查询

存在(exists)查询用于筛选某个字段不为空的文档,其作用类似于SQL的“is not null”语句的作用。先往索引test-3-2-1中添加一条数据,这条数据有一个age年龄字段。

POST test-3-2-1/_doc/5
{
  "id": "5",
  "sex": true,
  "name": "刘大",
  "born": "2020-02-18 00:02:20",
  "age": 20,
  "location": {
    "lat": 21.12,
    "lon": -71.34
  }
}

然后,使用exists查询查找age字段存在的数据。

POST test-3-2-1/_search
{
  "query": {
    "exists": {
      "field": "age"
    }
  }
}

1.3 正则查询

正则查询允许查询内容是正则表达式,它会查询出某个字段符合正则表达式的所有文档。例如:

.POST test-3-2-1/_search
{
  "query": {
    "regexp": {
      "name.keyword": ".*大.*"
    }
  }
}

1.4 匹配搜索

匹配搜索(match query)和术语查询(term query)不一样,匹配搜索会比较搜索词和每个文档的相似度,只要搜索词能命中文档的分词就会被搜索到,而term query要么搜不到,要么搜到的内容就和索引内容一模一样。Match query主要用于对指定的text类型的字段做全文检索。

先给索引ik-text和my_analyzer-text添加一些数据。

PUT ik-text/_doc/1
{
  "content":"武汉大学",
  "abstract":"200210452014"
}
PUT my_analyzer-text/_doc/1
{
  "content":"武汉大学",
  "abstract":"200210452014"
}

尝试用IK分词器来测试match query的效果。

POST ik-text/_search
{
  "query": {
    "match": {
      "content": {
        "query": "武汉大学是一所好学校",
        "analyzer": "ik_max_word"
      }
    }
  }
}

IK分词器有两种分词模式:ik_max_word和ik_smart模式。ik_max_word (常用) 会将文本做最细粒度的拆分,而ik_smart模式是做粗粒度的拆分,下面的可以看他们是如何划分的。

POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "武汉大学是一所好学校"
}

下面这个可以进行多个条件查询

POST ik-text/_search
{
  "query": {
    "match_bool_prefix" : {
      "content" : "武大 一所 武汉"
    }
  }
}

1.5 经纬度搜索

经纬度搜索在GIS开发中较为常见,比如你想在地图上搜索有哪些坐标点落在某个圆形、矩形或者多边形的区域内,这时经纬度搜索就会特别管用。

1.5.1 圆形搜索

圆形搜索(geo-distance)用于搜索距离某个圆心一定长度的检索半径之内的全部数据,传参时需要传入圆心坐标和检索半径。
先新建一个索引geo-shop,并添加一些测试数据。

PUT geo-shop
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}
PUT geo-shop/_bulk
{"index":{"_id":"1"}}
{"name":"北京","location":[116.4072154982,39.9047253699]}
{"index":{"_id":"2"}}
{"name":"上海","location":[121.4737919321,31.2304324029]}
{"index":{"_id":"3"}}
{"name":"天津","location":[117.1993482089,39.0850853357]}
{"index":{"_id":"4"}}
{"name":"顺义","location":[116.6569478577,40.1299127031]}
{"index":{"_id":"5"}}
{"name":"石家庄","location":[114.52,38.05]}
{"index":{"_id":"6"}}
{"name":"香港","location":[114.10000,22.20000]}
{"index":{"_id":"7"}}
{"name":"杭州","location":[120.20000,30.26667]}
{"index":{"_id":"8"}}
{"name":"青岛","location":[120.33333,36.06667]}

下面的请求会创建一个圆形搜索,它会搜索以经纬度[116.4107, 39.96820]为圆心,以100km为检索半径的城市列表。

POST geo-shop/_search
{
  "query": {
    "geo_distance": {
      "distance": "100km",
      "location": {
        "lat": 39.96820,
        "lon": 116.4107
      }
    }
  }
}

1.5.2 矩形搜索
与圆形搜索不同,矩形搜索(geo-bounding box)需要提供左上角(top_left)和右下角(bottom_right)的经纬度坐标,这样才能查出所有的矩形范围内的数据。例如:

POST geo-shop/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 40.82,
          "lon": 111.65
        },
        "bottom_right": {
          "lat": 36.07,
          "lon": 120.33
        }
      }
    }
  }
}

1.5.3 多边形搜索
多边形搜索(geo-polygon)需要传入至少3个坐标点的数据,geo-polygon会搜索出坐标点围成的多边形范围内的数据。例如:

POST geo-shop/_search
{
  "query": {
    "geo_polygon": {
      "location": {
        "points": [
          {
            "lat": 39.9,
            "lon": 116.4
          },
          {
            "lat": 41.8,
            "lon": 123.38
          },
          {
            "lat": 30.52,
            "lon": 114.31
          }
        ]
      }
    }
  }
}

1.6 布尔查询

布尔查询应该是项目开发中应用得很多的复合搜索方法了,它可以按照布尔逻辑条件组织多条查询语句,只有符合整个布尔条件的文档才会被搜索出来。在布尔条件中,可以包含两种不同的上下文。

(1)搜索上下文(query context):使用搜索上下文时,Elasticsearch需要计算每个文档与搜索条件的相关度得分,这个得分的计算需使用一套复杂的计算公式,有一定的性能开销,带文本分析的全文检索的查询语句很适合放在搜索上下文中。

(2)过滤上下文(filter context):使用过滤上下文时,Elasticsearch只需要判断搜索条件跟文档数据是否匹配,例如使用Term query判断一个值是否跟搜索内容一致,使用Range query判断某数据是否位于某个区间等。过滤上下文的查询不需要进行相关度得分计算,还可以使用缓存加快响应速度,很多术语级查询语句都适合放在过滤上下文中。布尔查询一共支持4种组合类型,它们的使用说明如表5.2所示。
在这里插入图片描述
下面发起一个布尔查询请求,如下所示。

POST test-3-2-1/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "张 刘 赵"
          }
        }
      ],
      "should": [
        {
           "range": {
             "age": {
               "gte": 10
             }
           }
        }
      ],
      "filter": [
        {
          "term": {
            "sex": "true"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "born": {
              "value": "2020-10-14 00:02:20"
            }
          }
        }
      ]
    }
  }
}

注意:虽然你可以把match放在filter里面,但是这样不会计算相关度得分,可能导致搜索结果的排序并不理想;你也可以把term放在must里面,但是这样就无法用到缓存,还要计算相关度得分,会导致查询变慢。因此,请在使用时养成好的搜索习惯,把需要文本分词的检索条件放到must里面,把不需要分词的检索条件放到filter里面。

1.7 析取最大查询

析取最大查询(disjunction max)允许添加多个查询条件,符合任意条件的文档就会被搜索到,每个文档的相关度得分取匹配搜索条件的最大的那一个值。某些文档可能会同时匹配多个搜索条件,但可能由于得分均不高而无法排名靠前,这时可以在查询中添加tie_breaker参数,将其他匹配的查询得分也计入在内。例如:

POST sougoulog/_search
{
  "query": {
   "dis_max": {
     "queries": [
       {"match": {"keywords": "火车"}},
       {"match": {"rank": "1"}}
      ],
      "tie_breaker": 0.8
   }
  },
  "from": 0,
  "size": 10
}

这个请求添加了两个match查询条件,还设置了tie_breaker为0.8,你可以把它的值设置为0~1范围内的任意小数,这个值越大,文档匹配的查询条件越多,排名就可以越靠前。该请求的搜索结果会返回至少匹配了一个match查询条件的文档。

1.8 相关度增强查询

相关度增强查词(boosting query)包含一个positive查询条件和一个negative查询条件,该查询会返回所有匹配positive查询条件的相关文档,在这些返回的文档中,匹配negative查询条件的文档相关度得分会降低,得分降低的程度可以使用negative_boost参数进行控制。例如:

POST sougoulog/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {"keywords": "车"}},
      "negative": {
        "range": {"rank": {"lte": 10}
        }
      },
      "negative_boost": 0.5
    }
  }
}

上述代码会返回所有keywords字段包含“车”的文档,但是对于rank字段小于等于10的文档会将相关度乘0.5作为最后得分。上述代码会使符合negative查询条件的搜索结果的文档排序靠后,而其他文档的排序则靠前。

1.9 搜索结果的总数

从Elasticsearch 7.x开始,搜索结果中的total值会带有value和relation两个字段,当搜索结果总数小于等于10000时,返回的relation为“eq”,表示此时的搜索结果的总数是准确的。一旦搜索结果的总数超过10000,就默认会返回下面的内容。

"hits" : {
    "total" : {
      "value" : 10000,
      "relation" : "gte"
    },

发现此时搜索结果的relation变成了“gte”,表示实际的总数值比现在返回的值10000要大。默认最大只能返回10000,这样设置是为了在不需要搜索结果的精确总数时可以提高查询性能。如果想获得搜索结果的准确总数,需要在查询中将参数track_total_hits设置为true。

"query": {
    "match_all": {}
  },
  "track_total_hits": true

2.0 Search after分页

滚动分页无法实时显示最新的数据,Search after分页则可以有效避免这个问题,它的原理是每次根据上一次分页的最后一条记录的位置来寻找下一页的记录。使用时先发起一个查询请求获取第一页的数据,与普通分页的唯一区别在于,这个查询请求必须添加一个唯一字段来进行排序,如果你的映射中没有唯一字段,可以使用文档自带的主键字段“_id”。例如:

POST sougoulog/_search
{
  "query": {
    "match_all": {}
  },
  "track_total_hits": true,
  "size": 10,
  "from": 0,
  "sort": [
    {
      "id": {
        "order": "asc"
      }
    }
  ]
}

上述代码会取出搜索结果的前10条记录,数据按照唯一的字段id进行升序排列,在以下结果中你只需要关注最后一条数据的sort值。

{
        "_index" : "sougoulog",
        "_type" : "_doc",
        "_id" : "10",
        "_score" : null,
        "_source" : {
          "clicknum" : 2,
          "id" : 10,
          "keywords" : "[电脑创业]",
          "rank" : 2,
          "url" : "ks.cn.yahoo.com/question/1307120203719.html",
          "userid" : "9975666857142764",
          "visittime" : "00:00:00"
        },
        "sort" : [
          10
        ]
      }

再把这个sort值10作为search_after分页的参数传入下一次分页的请求,就能得到下一页的数据了。

POST sougoulog/_search
{
  "query": {
    "match_all": {}
  },
  "track_total_hits": true,
  "size": 10,
  "from": 0,
  "sort": [
    {
      "id": {
        "order": "asc"
      }
    }
  ],
  "search_after": [10]
}

注意:在使用search_after参数的查询中,from参数必须为0,否则会报错。另外,排序选择的字段必须是唯一的,不然会因为该字段相同的数据无法决定先后顺序导致分页的结果不正确。

sort 是用来进行排序的,在指定排序字段时,不可以直接将分词的text类型字段作为排序依据,因为text类型字段没有在磁盘上保存doc value值,而且这样做在业务上没有任何意义。通常用来排序的字段是日期类型的字段、数值类型的字段、关键字类型的字段,可以多个字段进行排序的。

2.1 筛选搜索结果返回的字段

有时候索引的字段数目比较多,而前端并不需要展示或者导出这么多字段,这时候就需要对搜索结果返回的字段进行筛选。以下请求用_source参数筛选出需要返回的字段列表“born”和“name”。

POST test-3-2-1/_search
{
  "query": {
    "match_all": {}
  },
  "_source": [ "born", "name" ]
}

2.2 高亮搜索结果中的关键词

高亮是搜索引擎中很常见的功能,使用百度或者谷歌搜索引擎搜索内容的时候,被搜索的关键词会以高亮形式出现在搜索结果中。这个功能在实现时通常要用到倒排索引中像表2.2那样记录每个分词出现的位置信息,它们在文本分析的过程中就生成了。

高亮功能的使用比较简单,只需要在highlight中传入需要高亮显示的字段和高亮标签,默认的高亮标签是标签,你可以通过参数来自定义。例如:

POST my_analyzer-text/_search
{
  "query": {
    "query_string": {
      "query": "武术 \"210\""
    }
  },
  "highlight": {
    "pre_tags" : ["<tag1>"],
    "post_tags" : ["</tag1>"],
    "fields": {
      "abstract": {},
      "content": {}
    }
  }
}

这个请求表示在query_string查询的结果中,对abstract和content两个字段进行关键词高亮,使用了pre_tags和post_tags设置高亮标签。该请求会得到以下结果。

"hits" : [
      {
        "_index" : "my_analyzer-text",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.1507283,
        "_source" : {
          "content" : "武汉大学",
          "abstract" : "200210452014"
        },
        "highlight" : {
          "abstract" : [
            "200<tag1>2</tag1><tag1>1</tag1><tag1>0</tag1>452014"
          ],
          "content" : [
            "<tag1>武</tag1>汉大学"
          ]
        }
      }

2.3 折叠搜索结果

如果你想知道索引中某个字段存在哪些不同的数据,就可以使用搜索的折叠功能,它的效果类似于SQL中的“select distinct”的效果,只保留某个字段不重复的数据。

先建立一个索引collapse-test并导入测试数据。

POST collapse-test/_bulk
{"index":{"_id":"1"}}
{"id":"1","name":"王五","level":5,"score":90}
{"index":{"_id":"2"}}
{"id":"2","name":"李四","level":5,"score":70}
{"index":{"_id":"3"}}
{"id":"3","name":"黄六","level":5,"score":70}
{"index":{"_id":"4"}}
{"id":"4","name":"张三","level":5,"score":50}
{"index":{"_id":"5"}}
{"id":"5","name":"马七","level":4,"score":50}
{"index":{"_id":"6"}}
{"id":"6","name":"黄小","level":4,"score":90}

然后在查询中添加一个collapse参数,选择在level字段上进行数据折叠。

POST collapse-test/_search
{
  "query": {
    "match_all": {}
  },
  "collapse": {
    "field": "level"
  }
}

结果如下,每个level会选择一条数据进行展示。

"hits" : [
      {
        "_index" : "collapse-test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : "1",
          "name" : "王五",
          "level" : 5,
          "score" : 90
        },
        "fields" : {
          "level" : [
            5
          ]
        }
      },
      {
        "_index" : "collapse-test",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "id" : "5",
          "name" : "马七",
          "level" : 4,
          "score" : 50
        },
        "fields" : {
          "level" : [
            4
          ]
        }
      }
    ]

可以看到level字段重复的数据都被折叠了,两个level各显示了一条数据。如果想展示每个level所包含的详细数据,可以使用inner_hits参数来获取。

POST collapse-test/_search
{
  "query": {
    "match_all": {}
  },
  "collapse": {
    "field": "level",
    "inner_hits": {
      "name": "by_level",
      "size": 2,
      "sort": [ { "score": "asc" } ]
    }
  }
}

上面的请求在inner_hits中配置了每个相同的level数据最多展示两条,并且按照score字段升序排列,部分结果如下。

"hits" : [
      {
        "_index" : "collapse-test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : "1",
          "name" : "王五",
          "level" : 5,
          "score" : 90
        },
        "fields" : {
          "level" : [
            5
          ]
        },
        "inner_hits" : {
          "by_level" : {
            "hits" : {
              "total" : {
                "value" : 4,
                "relation" : "eq"
              },
              "max_score" : null,
              "hits" : [
                {
                  "_index" : "collapse-test",
                  "_type" : "_doc",
                  "_id" : "4",
                  "_score" : null,
                  "_source" : {
                    "id" : "4",
                    "name" : "张三",
                    "level" : 5,
                    "score" : 50
                  },
                  "sort" : [
                    50
                  ]
                },
                {
                  "_index" : "collapse-test",
                  "_type" : "_doc",
                  "_id" : "2",
                  "_score" : null,
                  "_source" : {
                    "id" : "2",
                    "name" : "李四",
                    "level" : 5,
                    "score" : 70
                  },
                  "sort" : [
                    70
                  ]
                }
              ]
            }
          }

可以看到level为5的数据一共有4条,但是只外显了2条。折叠效果可以嵌套到第二级,但是第二级不可以做inner_hits处理。例如下面的请求,我们在collapse参数中又嵌套了一个collapse,但是只能在第一个collapse中做inner_hits。

POST collapse-test/_search
{
  "query": {
    "match_all": {}
  },
  "collapse": {
    "field": "level",
    "inner_hits": {
      "name": "by_level",
      "size": 5,
      "sort": [ { "score": "asc" } ],
      "collapse": { "field": "score" }
    }
  }
}

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

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

相关文章

Python学习基础笔记六十七——格式化字符串

Printf-Style String Formatting: Printf风格字符串格式化 salary input(请输入薪资&#xff1a;)# 计算出缴税额&#xff0c;存入变量tax tax int(salary) *25/100 # 转化为字符串&#xff0c;方便下面的字符串拼接 taxStr str(tax) # 计算出税后工资&#xff0c;存入变…

Linux基础—1

1、命令行 1) 重要快捷键 按键作用Tab命令补全Ctrl强行终止当前程序Ctrld键盘输入结束或退出终端Ctrls暂停当前程序&#xff0c;暂停后按下任意键恢复运行Ctrlz将当前程序放到后台运行&#xff0c;恢复到前台为命令fgCtrla将光标移至输入行头&#xff0c;相当于Home键Ctrle将…

计算机操作系统-第六天

目录 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 操作系统的体系结构 关于微内核的相关理解&#xff1a; 本节思维导图&#xff1a; 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 内核是…

整理总结提高抖音小店商品转化率的五大策略

要提高抖音小店的商品转化率&#xff0c;即将浏览者转化为实际购买者&#xff0c;四川不若与众整理了需要注意的以下几个关键因素。 首先&#xff0c;优化商品页面设计。商品页面是消费者获取产品信息和决策的关键环节。商家应确保商品页面简洁清晰&#xff0c;配备高质量的产品…

Pytest+Allure生成可添加附件的测试报告

#测试套件层级 allure.feature("测试PecExplorer") #重试次数&#xff0c;粒度为用例&#xff0c;建议用例设计可重复性高 pytest.mark.flaky(reruns3) class TestPecExplorer:#功能模块层级allure.story("登录界面")#测试用例层级allure.title("Test…

C语言程序设计 三四节课堂笔记

C语言程序设计 三四节课堂笔记 C语言程序设计 三四节课堂笔记3.0 程序编写顺序&#xff08;了解&#xff09;3.1 C语言的特点3.2 认识C程序1. C程序的基本框架2. C语言程序的结构特点3. C程序的开发过程 C语言程序设计 第四节课4.1 开发环境dev-C的使用1. 如何将英文界面调整为…

Spring-Java

Spring&#xff1a; 图片出处&#xff1a;b站黑马 ssm学习截图 是一个大家族 &#xff0c;是一套完整的开发生态圈。可以利用这个spring全家桶快速构建企业级开发环境。 Spring Freamwork 是其他框架的基础 Springbot 使用了注解开发 SpringCloud 分布式 云服务 Sprin…

Leetcode—88.合并两个有序数组【简单】

2023每日刷题&#xff08;一&#xff09; Leetcode—88.合并两个有序数组 题解 因为这两个数组已经排好序&#xff0c;我们可以把两个指针分别放在两个数组的末尾&#xff0c;即 nums1 的m − 1 位和 nums2 的 n − 1 位。每次将较大的那个数字复制到 nums1 的后边&#xff0…

计算机操作系统面试题自用

什么是操作系统&#xff1a; 操作系统是管理硬件和软件的一种应用程序。操作系统是运行在计算机上最重要的一种软件 操作系统的主要功能 解释一下操作系统的主要目的是什么 操作系统是一种软件&#xff0c;它的主要目的有三种 1 管理计算机资源&#xff0c;这些资源包括 C…

LangChain结合milvus向量数据库以及GPT3.5结合做知识库问答之一 --->milvus的docker compose安装

https://github.com/milvus-io/milvus/releaseshttps://github.com/milvus-io/milvus/releases 以下步骤均在Linux环境中进行&#xff1a; 将milvus-standalone-docker-compose.yml下载到本地。 1、新建一个目录milvus 2、将milvus-standalone-docker-compose.yml放到milvu…

UWB承启定位基站

UWB承启定位基站 随着我们使用UWB做超高精度的定位项目越来越多&#xff0c;我们发现之前的定位基站完全站在二维或三维的角度去设计还是存在对应的缺陷&#xff0c;这个时候需要在很短的距离内安装多一个基站&#xff0c;对于用户来说&#xff0c;会觉得设备变多了&#xff0…

05在IDEA中配置Maven的基本信息

配置Maven信息 配置Maven家目录 每次创建Project工程后都需要设置Maven家目录位置&#xff0c;否则IDEA将使用内置的Maven核心程序和使用默认的本地仓库位置 一般我们配置了Maven家目录后IDEA就会自动识别到conf/settings.xml配置文件和配置文件指定的本地仓库位置创建新的P…

Java中的栈(Stack)为什么要采用先进后出

Java虚拟机栈 Java虚拟机栈是描述Java方法运行过程的内存模型。 当一个方法即将被运行时&#xff0c;Java虚拟机栈首先会在Java虚拟机栈中为该方法创建一块“栈帧”&#xff0c;栈帧中包含局部变量表(基本数据类型变量、引用类型的变量、returnAddress类型的变量)、操作数栈、…

小谈设计模式(29)—访问者模式

小谈设计模式&#xff08;29&#xff09;—访问者模式 专栏介绍专栏地址专栏介绍 访问者模式角色分析访问者被访问者 优缺点分析优点将数据结构与算法分离增加新的操作很容易增加新的数据结构很困难4 缺点增加新的数据结构比较困难增加新的操作会导致访问者类的数量增加34 总结…

windows10系统-16-制作导航网站WebStack-Hugo

上个厕所功夫把AI导航搞定了 使用Hugo搭建静态站点 如何使用Hugo框架搭建一个快如闪电的静态网站 1 Hugo 参考Hugo中文文档 参考使用Hugo搭建个人网站 Hugo是由Go语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。 1.1 安装Hugo 二进制安装&#xff08;推荐…

iMeta框架使用方法

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

判断一棵树是否为完全二叉树——层序遍历

完全二叉树&#xff08;包括满二叉树 &#xff09; 利用层序遍历&#xff0c;当取顶取到空的时候&#xff08;这个时候取的这一层的所有节点是一定在队列里面的&#xff09;&#xff0c;就结束入队&#xff0c;然后判断他的后面的节点是否都为空 这里重点还是要理解二叉树的层…

求二叉树的高度——函数递归的思想

二叉树的高度&#xff1a;左右两个数最高的那个的1 int TreeHight(BTNode* root) {if (root NULL){return 0;}int lefhightTreeHight(root->left);int righthight TreeHight(root->right);return lefhight > righthight ? TreeHight(root->left) 1 : TreeHight…

集合的进阶

不可变集合 创建不可变的集合 在创建了之后集合的长度内容都不可以变化 静态集合的创建在list &#xff0c;set &#xff0c;map接口当中都可以获取不可变集合 方法名称说明static list of(E …elements)创建一个具有指定元素集合list集合对象staticlist of(E…elements)创…

51系列—基于51单片机的RS232通信示例

一、目录 1、51单片机串口通信的应用 2、PC控制单片机IO口输出 3、51单片机控制实训指导及综合应用实例 4、51单片机给计算机发送数据 二、实验任务 单片机串口通信的应用&#xff0c;通过串口&#xff0c;我们的个人电脑和单片机系统进行通信。个人电脑作为上位机&#xff…