Elasticsearch实战(三)---复杂数据结构及映射 Mapping操作

2023-11-03

Elasticsearch实战-复杂数据结构及映射 Mapping操作

1.ElasticSearch 映射操作

基于文章 Elasticsearch实战(一)—安装及基本语法使用 前面的文章,我们已经基本使用了ES,但是我们对于底层知识还是不了解的,现在我们讲一下 底层结构

1.1 结构
  • 1.索引
  • 2.类型
  • 3.文档
MYSQL Elasticsearch
数据库DB 索引 Index
表table 类型type _doc
行 记录 record 文档 Documents
列 字段column 字段 Fields

逻辑设计:索引一篇文档时,通过顺序找到它:索引 -> 类型 -> 文档ID

1.2 映射

映射可以分为动态映射和显式映射

  • 动态映射 (dynamic mapping)
    在关系数据库中,需要事先创建数据库,然后在该数据库实例下创建数据表,然后才能在该数据表中插入数据。而 ElasticSearch中 不需要事先定义映射(Mapping),文档写入 ElasticSearch 时,会根据文档字段自动识别类型,这种机制称之为动态映射, 像我们前几篇文章中 直接操作 put /test/-doc/1 插入数据就是 动态映射,并没有提前建立映射,根据自动插入的内容去映射信息
#  插入数据
PUT /jzj/_doc/1
{
  "name":"jzj",
  "age":10,
  "address":"湖北省武汉市"
}

查看映射

GET /jzj/_mapping

可以看到 address:type:text 类型文本, age:type:long 整数, name:type:text 文本
除 text 外其他类型不会进行分词 , 所以其他类型必须要进行精确查询
在这里插入图片描述

1.3 映射-显式映射

映射可以分为动态映射和显式映射

  • 显式映射(explicit mappings)
    在 ElasticSearch 中也可以事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为显式映射。显示映射适用于事先直到结构,然后部分字段要定义使用其它分词器、是否分词、是否存储等
# 新建索引
PUT /jzjshow
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
    "mappings" : {
      "properties" : {
        "address" : {
          "type" : "text",
          "analyzer": "standard",
          "search_analyzer": "standard"
        },
        "addtime" : {
          "type" : "date"
        },
        "age" : {
          "type" : "long"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
        }
      }
    }

新建显式索引
在这里插入图片描述
然后 插入数据

PUT /jzjshow/_doc/1
{
  "address":"湖北省武汉市",
  "addtime": "2022-05-01",
  "age":20,
  "name":"测试人员"
}

查询结果
在这里插入图片描述

2.ElasticSearch 数据类型
2.1 基本数据类型
  • 字符串:text 。
    text:当一个字段是要被全文搜索的,比如 Email 内容、产品描述,应该使用 text 类型。设置 text 类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text 类型的字段不能排序,很少用于聚合

  • 字符串:keyword
    keyword:该类型不需要进行分词,可以被用来检索过滤、排序和聚合,keyword 类型的字段只能通过精确匹配

  • 整数:byte, short, integer, long

  • 浮点数:float, double

  • 布尔:boolean

  • 日期:date,JSON 本身并没有日期数据类型
    ES 中的日期类型可以是: 2015-01-01 or 2015/01/01 12:10:30 的字符串
    long 类型的毫秒级别的时间戳
    int 类型的秒级别的时间戳

  • 二进制型:`binary``,二进制类型以 Base64 编码方式接收一个二进制值,二进制类型字段默认不存储,也不可搜索。

简单操作 插入 日期,boolean,整数 类型的字段, 依次插入四条数据

PUT /jzjshow/_doc/1
{
  "address":"湖北省武汉市",
  "addtime": "2022-05-01",
  "age":20,
  "name":"测试人员"
}

PUT /jzjshow/_doc/2
{
  "address":"湖北省武汉市",
  "addtime": "2021-04-14T21:16:42.000Z",
  "age":20,
  "name":"测试人员"
}
PUT /jzjshow/_doc/3
{
  "address":"湖北省武汉市",
  "addtime": "2021-04-14",
  "age":20,
  "name":"测试人员"
}


PUT /jzjshow/_doc/4
{
  "address":"湖北省武汉市",
  "addtime": "1654413037",
  "age":20,
  "name":"测试人员"
}

PUT /jzjshow/_doc/4
{
  "address":"湖北省武汉市",
  "addtime": "1654413037000",
  "age":20,
  "name":"测试人员"
}

可以看到查询结果, 数据成功插入, 查询结果如下
第一条 yyyy-mm-dd, 数据存储也是 yyyy-mm-dd
第二条 UTC时间 , 数据存储也是 UTC时间
第三条 是Integer 时间戳 秒, 数据存储转换成了 yyyy-mm-dd
第四条是 Long 毫秒, 数据存储依旧是 Long毫秒

在这里插入图片描述

2.2 复杂数据类型 - 数组

在 ElasticSearch 中,没有专门的数组(Array)数据类型, 不需要进行任何配置,就可以直接使用。

在默认情况下,任意一个字段都可以包含 0 或多个值,这意味着每个字段默认都是数组类型,只不过,数组类型的各个元素值的数据类型必须相同:

  • 字符串数组: [ “one”, “two” ]
  • 整型数组: [ 1, 2 ]
  • 数组数组: [ 1, [ 2, 3 ]] which is the equivalent of [ 1, 2, 3 ]
  • 对象数组: [ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]

注意:
动态添加数据时,数组的第一个值的类型决定整个数组的类型
混合数组类型是不支持的,比如:[1,”abc”]
数组可以包含 null 值,空数组 [ ] 会被当做 missing field 对待

数组存储结构会被扁平化处理

put /jzjarr/_doc/1
{
    "title":"人员列表"
  ,
  "person":[
    {
    "name":"joy",
    "age":20,
    "address":"湖北省"
    },
    {
    "name":"zhangsan",
    "age":40,
    "address":"河北省"
    },
    {
    "name":"lisi",
    "age":30,
    "address":"河南省"
    }
    ]
}

对于ES来说 会把数组扁平化处理成 , 查询的时候 对于array数组内部的元素就要用 person.name来处理

title:[“人”,“员”,“列“,”表”]
person.name:["joy", "zhangsan", "lisi"]
peson.age:[20,40,30]
person.address:[“湖北省”,“河北省”,“河南省”]

这样的数据, 就会导致 {“name”:“joy”, “age”:20, “address”:“湖北省” } 没了关联性
比如要查询 age=20 且 address=“河南省” 的信息 , 期望是查不到的,因为 person中不包含这样的信息

get /jzjarr/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "person.age": "20"
          }
        },
         {
          "match": {
            "person.address": "河南省"
          }
        }
      ]
    }
  }
}

查询结果, 出现了不匹配的情况, 明明是查询 age=20 且 address=河南省, 没有这种记录,但是搜到了其他的记录 在这里插入图片描述
这种问题 后面用 复杂结构Nested来处理 即可

2.3 复杂数据类型 -对象Object

JSON 文档是有层次结构的,一个文档可能包含其他文档,如果一个文档包含其他文档,那么该文档值是对象类型,其数据类型是对象,ES 默认把文档的属性 type设置为 object,即 “type”:“object”。

比如我现在有个嵌套文档 say 下面有三种语言, 可以看到 name 及 say 字段都是嵌套的 Json对象,say下面还有子对象 {chinese:你好 }, 如果没有明确给出 type类型,默认类型就是 type:Object对象类型

# 插入数据
put /jzjsay/_doc/1
{
  "name":{
    "first":"joy",
    "last":"boy"
  },
  "age":20,
  "say":{
    "chinese":"你好",
    "english":"hello",
    "japan":"hai"
  }
}

对于Object对象 我们要如何进行查询?
通过对象类型Object来存储二级文档,因为 Lucene 并没有内部对象的概念,ES 会将原 JSON 文档扁平化
上面的对象类型,ES在索引时将其转换为"name.first", “say.chinese” 这样扁平的key,用这样的扁平key作为域来进行查询

如果采用 name 或者 first 单独查询是无法查询的
在这里插入图片描述
必须使用 扁平化索引 eg name.first 或者 say.chinese 来实现

#扁平化索引 name.first
GET /jzjsay/_search
{
  "query":{
    "match": {
      "name.first": "joy"
    }
  }
}


#扁平化索引 say.chinese
get /jzjsay/_search
{
  "query":{
    "match": {
      "say.chinese": "你"
    }
  }
}

在这里插入图片描述

2.4 Object 对象类型 存在的问题

我们上面看了Object 存储这样的结构,看似没问题,可以通过索引去查询出来想要的结构 因为 底层是扁平化存储的数据

  • name.first, name.last
  • say.chinese, say.english, say.japan

但是我们看 下下面的场景, 先插入1 条比较复杂的数据
有一个 张三的同学, 三个人给了他评论
评论人 one, age=20 ,评价 good job
评论人 two, age=30, 评价 bad job
评论人 three,age=40, 评价 normal job

put /jzjcomment/_doc/1
{
 "name":"张三",
 "tags":["优秀", "好"],
 "comments":[
   {
     "name":"one",
     "age":20,
     "say":"good job"
   },
   {
     "name":"two",
     "age":30,
     "say":"bad job"
   }
   ,
   {
     "name":"three",
     "age":40,
     "say":"normal job"
   }
   ]
}

我现在想 查询 评价人是 one 的, 且 One的 年龄是30岁的 记录信息
按道理说是 找不到的, 因为 第一个评价人 One的年龄是 20, 查询语句应该查不到,我们试一下

# 查询 评价人年龄是30岁  且 评价人名字是 one的 那条记录
# bool 过滤, must And操作   "comments.age": 30 且  "comments.name": "one" 
GET /jzjcomment/_search
{
 "query": {
   "bool": {
     "must": [
       {
         "match": {
           "comments.age": 30
         }
       },
       {
         "match": {
           "comments.name": "one"
         }
       }
     ]
   }
 }
 
}

查询结果, 出现一条,明明 评价人 One的年龄是20 岁, 我的 must And操作是 姓名=one 且 年龄是30岁, 为什么能把这条记录查出来?
在这里插入图片描述

因为Object 存储结构的问题
Object结构 的 JSON 文档在 Lucene 底层会被打平成一个简单的键值格式,就像这样:
{
“name”: [“张”, “三”],
“tags”: [“优秀”, “好”],
“comments.name”: [“one”,“two”,“three”],
“comments.age”: [20, 30,40],
“comments.say”: [“good job”, “bad job”, “normal job”]
}
这样 底层查询就是 one in comments.name , age=30 in commemts.age 已经没有顺序性了,没有了 one 打了 20分, 评语是 goodjob 这一条记录的关联性丢失了
所以 Object结构是有缺陷的,所以 才有了Nested结构

2.5 复杂结构类型 -Nested

针对上面的 记录 Nested 是如何存储的?每一个 comments 都是一个单独的Document来处理, 如下
{
“name”: [“张”, “三”],
“tags”: [“优秀”, “好”],
{
“comments.name”: [“one”],
“comments.age”: [20],
“comments.say”: [“good” ,“job”]
},
{
“comments.name”: [“two”],
“comments.age”: [30],
“comments.say”: [“bad” ,“job”]
},
{
“comments.name”: [“three”],
“comments.age”: [40],
“comments.say”: [“normal” ,“job”]
}
}

在查询的时候将根文档 和 nested 文档拼接是很快的。
这些额外的 nested objects 文档是隐藏的,为了更新、增加或者移除一个 nested 对象,必须重新插入整个文档。
查询请求返回的结果不仅仅包括 nested 对象,而是整个文档

重新插入 Nested结构的文档

# 插入 Nested结构的文档 comments type:nested
put /jzjcommentnested
{
      "mappings" : {
      "properties" : {
        "comments" : {
          "type":"nested",
          "properties" : {
            "age" : {
              "type" : "long"
            },
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "say" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "tags" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

查看一下 mapping 映射结构

get /jzjcommentnested/_mapping

在这里插入图片描述

再用刚才的 查询语句 查一下, 查询 评论人 one 且 年龄是30 岁 的 记录

 # 查询 评价人年龄是30岁  且 评价人名字是 one的 那条记录
 # bool 过滤, must And操作   "comments.age": 30 且  "comments.name": "one" 
GET /jzjcommentnested/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "comments.age": 30
          }
        },
        {
          "match": {
            "comments.name": "one"
          }
        }
      ]
    }
  }
}

同样的语句, 不一样的结果, 查不到 评论人 one 且年龄是30岁 的记录, 这才是我们预期结果
在这里插入图片描述

2.6 Nested 类型搜索 nested:{path:“”}

nested 作为一个独立隐藏文档单独建索引,因此,我们不能直接查询它们。所以 我们必须使用 nested 查询或者 nested filter 来获取 整个文档信息

对于刚才结构 jzjcommentnested, 再插入3条数据

put /jzjcommentnested/_doc/1
{
  "name":"张三",
  "tags":["优秀", "好"],
  "comments":[
    {
      "name":"one",
      "age":20,
      "say":"good job"
    },
    {
      "name":"two",
      "age":30,
      "say":"bad job"
    }
    ,
    {
      "name":"three",
      "age":40,
      "say":"normal job"
    }
    ]
}

put /jzjcommentnested/_doc/2
{
  "name":"李四",
  "tags":["完美", "好"],
  "comments":[
    {
      "name":"one",
      "age":20,
      "say":"bad job"
    },
    {
      "name":"two",
      "age":30,
      "say":"bad job"
    }
    ,
    {
      "name":"three",
      "age":40,
      "say":"good job"
    }
    ]
}

put /jzjcommentnested/_doc/3
{
  "name":"王五",
  "tags":["一般", "良好"],
  "comments":[
    {
      "name":"one",
      "age":60,
      "say":"normal job"
    },
    {
      "name":"two",
      "age":30,
      "say":"bad job"
    }
    ,
    {
      "name":"three",
      "age":40,
      "say":"good job"
    }
    ]
}

查询结果 3条

get /jzjcommentnested/_search

在这里插入图片描述

如何用Nested 来进行查询? 需要指定 path

# 原来的方式 是查不到 隐藏文档的  错误的查询方式
get /jzjcommentnested/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "comments.age": 60
          }
        },
                {
          "match": {
            "comments.name": "one"
          }
        }
      ]
    }
  }
}

必须使用 嵌套 Nested path 路径

# 查询 nested 嵌套 文档 comments 下面的 age 及 name信息
get /jzjcommentnested/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "comments.age": "20"
                    }
                  },
                  {
                    "match": {
                      "comments.name": "one"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

查询结果 也是正确的, 把嵌套的nested文档 张三 和 李四 两条结果查询出来
在这里插入图片描述

如果 需要关联 父 层的 结构 该如何查询, 比如 我要查 name=张三的 且 comments 内层 age=20, name = one的 记录

# 关联 父结构的 字段 name=张三
get /jzjcommentnested/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "name": "张三"
          }
        },
        //nested 文档查询方式
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "comments.age": "20"
                    }
                  },
                  {
                    "match": {
                      "comments.name": "one"
                    }
                  }
                ]
              }
            } 
           
          }
        }
      ]
    }
  }
}

查询结果 只有1条 张三这一条 且 匹配 嵌套 comments 内层 age=20, name = one的 记录
在这里插入图片描述

2.7 Nested 嵌套查询 sort排序

如果要基于Nested 中的文档排序,该如何实现? 我们看下官网的例子

先创建索引

    "mappings" : {
      "properties" : {
        "body" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "comments" : {
          "properties" : {
            "age" : {
              "type" : "long"
            },
            "comment" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "date" : {
              "type" : "date"
            },
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "stars" : {
              "type" : "long"
            }
          }
        },
        "tags" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }

然后 插入 文档 1, 文档 2

PUT /blog/_doc/1
{
    "title":"Nest eggs",
    "body":"Making your money work...",
    "tags":[
        "cash",
        "shares"
    ],
    "comments":[
        {
            "name":"John Smith",
            "comment":"Great article",
            "age":28,
            "stars":4,
            "date":"2014-09-01"
        },
        {
            "name":"Alice White",
            "comment":"More like this please",
            "age":31,
            "stars":5,
            "date":"2014-10-22"
        }
    ]
}
PUT /blog/_doc/2
{
    "title":"Nest eggs2",
    "body":"2Making your money work...",
    "tags":[
        "cash2",
        "shares2"
    ],
    "comments":[
        {
            "name":"John Smith2",
            "comment":"Great article",
            "age":28,
            "stars":3,
            "date":"2014-09-01"
        },
        {
            "name":"Alice White2",
            "comment":"More like this please",
            "age":31,
            "stars":2,
            "date":"2014-10-22"
        }
    ]
}

然后 执行 sort语句

GET /blog/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "range": {
          "comments.date": {
            "gte": "2014-10-01",
            "lt": "2014-11-01"
          }
        }
      }
    }
  },
  "sort": {
    "comments.stars": {
      "order": "asc",
      "mode": "min"
    }
  }
}

不管是 order asc 还是desc 都是这个顺序 这个让我疑问很大,不知道哪里出了问题


至此 我们复杂的结构已经介绍完毕, 并且基本的查询也已经介绍完毕, 下一篇 ,我们介绍下Nested聚合的使用场景

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Elasticsearch实战(三)---复杂数据结构及映射 Mapping操作 的相关文章

随机推荐

  • 跳出ping++退款的坑

    近期在项目的开发过程中 需要用到ping 的退款功能 由于使用的版本比官方提供的要低2个小版本 因此问题并不是很大 但是由于官方文档有些内容写的比较含蓄 因此遇到了一些问题 我们可以通过如下的方式来获取SDK的版本 gt gt gt imp
  • STM32开发环境配置相关问题记录

    1 编译时出现 error 35 error directive Please select first the target STM32F10x device used 解决方案 点选options for target 选择C C 在d
  • K8S deployment挂载

    Deployment部署文件 apiVersion apps v1 kind Deployment metadata annotations deployment kubernetes io revision 1 kubectl kuber
  • Spring Security认证成功后回跳(解决前后端分离下OAuth2认证成功回跳)

    前言 Spring Security 后面简称SS 用了很长时间了 但之前一直没注意到一个有趣的特性 直到最近弄前后端分离 在OAuth2提供者 github 认证后 需要跳回前端页面 前端页面和服务端不在同个域下 然后突然一般情况下 同域
  • 鸿蒙系统做服务器,鸿蒙升级第一夜服务器崩了,有人等到凌晨3点,称升级后内存变大...

    编 赵艳秋 6月2日晚间 华为宣布推出HarmonyOS 2 华为 百 款设备将陆续启动HarmonyOS 2升级 不少华为用户则经历了艰难的一夜 最大规模升级第一夜服务器崩了 有如五一小长假期间的在线购票系统12306 6月2日晚 因为太
  • 半径为r的均匀带电球体_放于真空中半径为R,带电量为q的均匀带电球体,求球内外各点电势分布...

    展开全部 当半径r 一个均匀带电的球壳 带电量为q 则e68a84e8a2ad62616964757a686964616f31333431353338对壳外部产生的场强为E q 4 r 内部场强为零 则以上均匀带电的球内半径为r处 电场强度
  • C语言删除字符串中某一指定字符

    include
  • Python数据挖掘和解析算法

    机器学习是计算机科学的一个分支 它利用过去的经验来学习并利用其知识来做出未来的决策 机器学习是计算机科学 工程和统计学的交叉点 机器学习的目标是概括一个可检测的模式或从给定的例子中创建一个未知的规则 机器学习领域的概述如下 监督学习 这是教
  • 11.3外汇黄金价格投资策略、期货原油最新价格布局及指导

    黄金消息面与技术面解析 消息面 周二 11月2日 国际金价持稳 在通胀压力不断增加以及对经济增长放缓的担忧之际 市场参与者等待美联储本周政策会议结果 美国物价和薪资涨幅正处于数十年来的高位 本周可能让美联储官员面临挑战 分析师预计 在央行收
  • STM32串口烧写程序

    STM32烧写注意 1 必须使用串口1烧写 2 烧写 BOOT0置1 BOOT1置0 运行 BOOT0置0 BOOT1置任意 3 使用FLYMCU烧写软件 4 NRST引脚电路设计成悬空 按键按下 拉低 步骤 1 买一根 TTL串口线分别把
  • 全国各省、市、区(sql语句)

    文章目录 一 省份 数据表 二 市 数据表 注意 因为到县sql语句太多文章限字数上传不全 所以一半放到了另外的一篇文章上 三 上部分区 县 数据表 四 中部分区 县 数据表 五 下部分区 县 数据表 六 在在下部分区 县 数据表 返回项目
  • 股票分析,利用线性回归实时预测股价,只需要提供股票代码即可爬取相应股票数据并建模

    这里参考了别人的代码 并引用了tushare模块中定义的接口自动获取了依据 股票代码来获取数据 此篇文章提供了 1 一个简单通过接口爬取csv数据的方法 2 一个处理csv数据的简单方法 3 依据数据进行特征提取建立简单的股价预测模型 如下
  • 关于Pygame运行无响应问题的办法(已解决)

    目录 pygame程序运行时需要初始化 在关闭运行页面的时候无响应 pygame程序运行时需要初始化 如下代码运行后无反应 import sys import pygame size width height 600 400 screen
  • 华为机试2016

    编程题 最高分是多少 老师想知道从某某同学当中 分数最高的是多少 现在请你编程模拟老师的询问 当然 老师有时候需要更新某位同学的成绩 输入描述 输入包括多组测试数据 每组输入第一行是两个正整数N和M 0 lt N lt 30000 0 lt
  • 1.5.1 AlexNet

    目录 五 AlexNet 5 1 ReLU 激活函数 5 2 局部响应正则化 5 3 数据增强 5 4 Dropout 5 5 网络整体架构 5 6 小结 五 AlexNet AlexNet 是 2012 年第 3届 ILSVRC Imag
  • 【postgresql 基础入门】创建数据库的方法,存储位置,决定自己的数据的访问用户和范围

    创建数据库 专栏内容 postgresql内核源码分析 手写数据库toadb 并发编程 开源贡献 toadb开源库 个人主页 我的主页 管理社区 开源数据库 座右铭 天行健 君子以自强不息 地势坤 君子以厚德载物 系列文章 入门准备 pos
  • Qt

    Qt QListWidgetItem返回错误的背景颜色 始终返回颜色值为0 问题解决 使用场景 程序使用QListWidget显示一个列表 这个列表具有点击选择和再次点击取消选择的功能 点击之后需要更换背景色以表示被选中 由于软件有主题效果
  • Js动态加载CSS样式文件的2种方法

    动态加载CSS文件 这个时常会用到 一般搞前端 我们最先想到的就是用JS来实现 的确 JS可以很方便的控制CSS样式表文件的动态插入 以下两种方法 使用 一 使用 这点采用了YUI插件中的一个方法 有效解决了各大浏览器的兼容性问题 主要是使
  • 面试经典(25)--二叉查找树(搜索树)

    二叉搜索树是经典的数据结构 本文来总结一下二叉搜索树的插入和删除算法 插入算法 struct Node int key struct Node parent struct Node left struct Node right struct
  • Elasticsearch实战(三)---复杂数据结构及映射 Mapping操作

    Elasticsearch实战 复杂数据结构及映射 Mapping操作 文章目录 Elasticsearch实战 复杂数据结构及映射 Mapping操作 1 ElasticSearch 映射操作 1 1 结构 1 2 映射 1 3 映射 显