当前位置: 首页 > news >正文

MongoDB 索引和常用命令

一、基本常用命令

1.1 案例需求

        存放文章评论的数据存放到 MongoDB 中,数据结构参考如下,其中数据库为 articledb

专栏文章评论

comment

字段名称

字段含义

字段类型

备注

_id

ID

ObjectId或String

Mongo的主键的字段

articleid

文章ID

String

content

评论内容

String

userid

评论人ID

String

nickname

评论人昵称

String

createdatetime

评论的日期时间

Date

likenum

点赞数

Int32

replynum

回复数

Int32

state

状态

String

0:不可见;1:可见;

parentid

上级ID

String

如果为0表示文章的顶级评论

1.2 数据库操作

1.2.1 选择和创建数据库

        在 MongoDB 中,集合只有在内容插入后才会创建。 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

# 选择和创建数据库的语法格式
# 数据库名可以是满足以下条件的任意UTF-8字符串。
#     不能是空字符串("")
#     不得含有' '(空格)、.、$、/、\和\0 (空字符)
#     应全部小写
#     最多64字节
use 数据库名称# 如果数据库不存在则自动创建,例如,以下语句创建 spitdb 数据库
use articledb# 查看有权限查看的所有的数据库命令
show dbs 或 show databases# 查看正在使用的数据库命令
# MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test 数据库中。
db

        有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库,如下

        admin: 从权限的角度来看,这是 "root" 数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。

        local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合

        config: 当 Mongo 用于分片设置时,config 数据库在内部使用,用于保存分片的相关信息。

1.2.2 数据库的删除

# 会删除当前正在使用的库,主要用来删除已经持久化的数据库
db.dropDatabase()

1.3 集合操作

        集合,类似关系型数据库中的表。可以显示的创建,也可以隐式的创建。

1.3.1 集合的显示创建

# 集合的命名规范
#     集合名不能是空字符串""。
#     集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
#     集合名不能以"system."开头,这是为系统集合保留的前缀。
#     用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,
#     这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,
#     否则千万不要在名字里出现$。# 基本语法格式如下
# name: 要创建的集合名称
db.createCollection(name)# 创建一个名为 mycollection 的普通集合
db.createCollection("mycollection")# 查看当前库中的表
show collections 或 show tables

1.3.2 集合的隐式创建

        当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合。通常我们使用隐式创建文档即可。

1.3.3 集合的删除

# 语法格式如下
db.collection.drop() 或 db.集合.drop()# 要删除 mycollection 集合,
# 如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false
db.mycollection.drop()

1.4 文档操作

        文档(document)的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。

1.4.1 文档的插入

1):单个文档的插入

        使用 insert() save() 方法向集合中插入文档,语法如下:

db.collection.insert(<document or array of documents>,{writeConcern: <document>,ordered: <boolean>}
)

Parameter

Type

Description

document

document or array

要插入到集合中的文档或文档数组。((json格式)

writeConcern

document

插入时性能和可靠性的级别,了解即可。

ordered

boolean

可选。如果为真,则按顺序插入数组中的文档,如果其中一个文档出现错误,MongoDB将返回而不处理数组中的其余文档。如果为假,则执行无序插入,如果其中一个文档出现错误,则继续处理数组中的主文档。在版本2.6+中默认为true

        接下来我们要向 comment 的集合(表)中插入一条测试数据,执行下面语句:

# 示例代码
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null}
)

提示: 

        1)comment 集合如果不存在,则会隐式创建。

        2)mongo 中的数字,默认情况下是 double 类型,如果要存整型,必须使用函数NumberInt(整型数字),否则取出来就有问题了。

        3)插入当前日期使用 new Date()

        4)插入的数据没有指定 _id ,会自动生成主键值

        5)如果某字段没值,可以赋值为 null,或不写该字段。

        出现下面的内容就证明插入成功了

注意:

        1. 文档中的键/值对是有序的。

        2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。

        3. MongoDB 区分类型和大小写。

        4. MongoDB 的文档不能有重复的键。

        5. 文档的键是字符串。除了少数例外情况,键可以使用任意 UTF-8 字符。 

文档键命名规范:

        1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。

        2、.和$有特别的意义,只有在特定环境下才能使用。

        3、以下划线 "_" 开头的键是保留的(不是严格要求的)。

2):多个文档的插入

   使用 insertMany() 方法向集合中插入多个文档,语法如下:

db.collection.insertMany([ <document 1> , <document 2>, ... ],{writeConcern: <document>,ordered: <boolean>}
)

        接下来我们要向 comment 的集合(表)中插入多条文章评论,执行下面语句:

db.comment.insertMany([{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}
]);

提示:

        如果插入时指定了 _id ,则主键就是该值。如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。

        因为批量插入由于数据较多容易出现失败,因此,可以使用 try catch 进行异常捕捉处理,测试的时候可以不处理。如(了解):

try {db.comment.insertMany([{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},{"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"},{"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);
} catch (e) {print (e);
}

1.4.2 文档的查询

# 查询数据的语法格式如下:
db.collection.find(<query>, [projection])

Parameter

Type

Description

query

document

可选。使用查询运算符指定选择筛选器。若要返回集合中的所有文档,请省略此参数或传递空文档( {} )。

projection

document

可选。指定要在与查询筛选器匹配的文档中返回的字段(投影)。若要返回匹配文档中的所有字段,请省略此参数。

1)查询所有

db.comment.find()
或
db.comment.find({})

        这里你会发现每条文档会有一个叫 _id 的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段,MongoDB 会自动创建,其类型是 ObjectID 类型。

        如果我们在插入文档记录时指定该字段也可以,其类型可以是 ObjectID 类型,也可以是MongoDB 支持的任意类型。 

        如果我想按一定条件来查询,比如我想查询 userid 1003 的记录,怎么办?很简单!只要在 find() 中添加参数即可,参数也是 json 格式,如下:

# 查询指定条件的数据
db.comment.find({userid:'1003'})

        如果你只需要返回符合条件的第一条数据,我们可以使用 findOne 命令来实现,语法和 find 一样。

# 查询用户编号是 1003 的记录,但只最多返回符合条件的第一条记录:
db.comment.findOne({userid:'1003'})

2)投影查询

        如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段),其中 _id 字段会默认显示。

# 查询结果只显示 _id、userid、nickname 字段
db.comment.find({userid:"1003"},{userid:1,nickname:1})

# 查询结果只显示 、userid、nickname ,不显示 _id
db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0})

# 查询所有数据,但只显示 _id、userid、nickname
db.comment.find({},{userid:1,nickname:1})

1.4.3 文档的更新

        更新文档的语法如下:

db.collection.update(query, update, options)//或
db.collection.update(<query>,<update>,{upsert: <boolean>,multi: <boolean>,writeConcern: <document>,collation: <document>,arrayFilters: [ <filterdocument1>, ... ],hint: <document|string> // Available starting in MongoDB 4.2}
)

        只需要关注前四个参数就可以了 

Parameter

Type

Description

query

document

更新的选择条件。可以使用与 find() 方法中相同的查询选择器,类似 sql update 查询内 where 后面的。在 3.0 版中进行了更改:当使用 upsert:true 执行 update() 时,如果查询使用点表示法在 _id 字段上指定条件,则 MongoDB 将拒绝插入新文档。

update

document or pipeline要应用的修改。该值可以是:包含更新运算符表达式的文档,或仅包含:对的替换文档

upsert

boolean

可选。如果设置为 true,则在没有与查询条件匹配的文档时创建新文档。默认值为 false,如果找不到匹配项,则不会插入新文档。

multi

boolean

可选。如果设置为 true,则更新符合查询条件的多个文档。如果设置为 false,则更新一个文档。默认值为 false。

writeConcern

document

可选。表示写问题的文档。抛出异常的级别。

collation

document

可选。指定要用于操作的校对规则。校对规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音标记的规则。

arrayFilters

array

可选。一个筛选文档数组,用于确定要为数组字段上的更新操作修改哪些数组元素。

hint

Document or string

可选。指定用于支持查询谓词的索引的文档或字符串。该选项可以采用索引规范文档或索引名称字符串。如果指定的索引不存在,则说明操作错误。例如,请参阅版本4中的“为更新操作指定提示。

1):覆盖的修改

# 修改_id为1的记录,点赞量为1001
db.comment.update({_id:"1"},{likenum:NumberInt(1001)})

        执行完上面的语句后,我们会发现,这条文档除了 likenum 字段其它字段都不见了 

2):局部修改

        为了解决这个问题,我们需要使用修改器 $set 来实现,命令如下 

# 修改 _id 为 2 的记录,浏览量为 889
db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})

        这样执行就可以更新指定的字段了,如下所示 

3):批量的修改

# 默认只修改第一条数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒2"}})# 修改所有符合条件的数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})

4):列值增长的修改

        如果我们想实现对某列值在原有值的基础上进行增加或减少,可以使用 $inc 运算符来实现。

# 对3号数据的点赞数,每次递增1
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

1.4.4 文档的删除

# 删除文档的语法结构
db.集合名称.remove(条件)# 将数据全部删除,请慎用
db.comment.remove({})# 删除_id=1的记录,输入以下语句
db.comment.remove({_id:"1"})

1.5 文档的分页查询

1.5.1 统计查询

        统计查询使用 count() 方法,语法如下:

# 可选项 options 暂时不使用
# 默认情况下 count() 方法返回符合条件的全部记录条数
db.collection.count(query, options)

Parameter

Type

Description

query

document

查询选择条件。

options

document

可选。用于修改计数的额外选项。

1):统计所有记录数

# 统计 comment 集合的所有的记录数
db.comment.count()

2):按条件统计记录数

# 统计 userid 为 1003 的记录条数
db.comment.count({userid:"1003"})

1.5.2 分页列表查询

        可以使用 limit() 方法来读取指定数量的数据,使用 skip() 方法来跳过指定数量的数据。基本语法如下所示:

db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

        如果你想返回指定条数的记录,可以在 find() 方法后调用 limit 来返回结果( TopN),默认值是 20,例如: 

# 返回 3 条记录
db.comment.find().limit(3)

        skip() 方法同样接受一个数字参数作为跳过的记录条数。(前 N 个不要),默认值是 0

# 跳过前 3 条记录
db.comment.find().skip(3)

        分页查询,每页显示 2 条数据,第二页显示第 3 和第 4 条数据。

# 第一页
db.comment.find().skip(0).limit(2)
# 第二页
db.comment.find().skip(2).limit(2)
# 第三页
db.comment.find().skip(4).limit(2)

1.5.3 排序查询

        sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。语法如下所示:

db.COLLECTION_NAME.find().sort({KEY:1})
或
db.集合名称.find().sort(排序方式)
# 对 userid 降序排列,并对访问量进行升序排列
db.comment.find().sort({userid:-1,likenum:1})

提示:

        skip()limilt(), sort() 三个方法放在一起执行的时候,执行的顺序是先 sort(),然后是 skip(),最后是显示的 limit(),和命令编写顺序无关。 

1.6 文档的更多查询

1.6.1 复杂条件查询

        MongoDB 的模糊查询是通过正则表达式的方式实现的。格式为:

# 正则表达式是 js 的语法,直接量的写法
db.collection.find({field:/正则表达式/})
或 
db.集合.find({字段:/正则表达式/})
# 查询评论内容包含 “开水” 的所有文档
db.comment.find({content:/开水/})# 要查询评论的内容中以 “专家” 开头的
db.comment.find({content:/^专家/})

1.6.2 比较查询

# 大于: field > value
db.集合名称.find({ "field" : { $gt: value }}) # 小于:field < value
db.集合名称.find({ "field" : { $lt: value }}) # 大于等于: field >= value
db.集合名称.find({ "field" : { $gte: value }}) # 小于等于: field <= value
db.集合名称.find({ "field" : { $lte: value }}) # 不等于: field != value
db.集合名称.find({ "field" : { $ne: value }}) 
# :查询评论点赞数量大于 700 的记录
db.comment.find({likenum:{$gt:NumberInt(700)}})

1.6.3 包含查询

        包含使用 $in 操作符,不包含使用 $nin 操作符

# 查询评论的集合中 userid 字段包含 1003 或 1004 的文档
db.comment.find({userid:{$in:["1003","1004"]}})# 查询评论集合中 userid 字段不包含 1003 和 1004 的文档
db.comment.find({userid:{$nin:["1003","1004"]}})

1.6.4 条件查询

        我们如果需要查询同时满足两个以上条件,需要使用 $and 操作符将条件进行关联。(相当于 SQL and)格式如下:

$and:[ { },{ },{ } ]
# 查询评论集合中likenum大于等于700 并且小于2000的文档
db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})

        如果两个以上条件之间是或者的关系,我们使用 $or 操作符进行关联,与前面 and 的使用方式相同格式为:

$or:[ { },{ },{ } ]
# 查询评论集合中 userid 为 1003,或者点赞数小于 1000 的文档记录
db.comment.find({$or:[ {userid:"1003"} ,{likenum:{$lt:1000} }]})

1.7 常用命令小节

# 选择切换数据库
use articledb# 插入数据
db.comment.insert({bson数据})# 查询所有数据
db.comment.find()# 条件查询数据
db.comment.find({条件})# 查询符合条件的第一条记录
db.comment.findOne({条件})# 查询符合条件的前几条记录
db.comment.find({条件}).limit(条数)# 查询符合条件的跳过的记录
db.comment.find({条件}).skip(条数)# 修改数据
db.comment.update({条件},{修改后的数据}) 或 db.comment.update({条件},{$set:{要修改部分的字段:数据})# 数据并自增某字段值
db.comment.update({条件},{$inc:{自增的字段:步进值}})# 删除数据
db.comment.remove({条件})# 统计查询
db.comment.count({条件})# 模糊查询
db.comment.find({字段名:/正则表达式/})# 条件比较运算
db.comment.find({字段名:{$gt:值}})# 包含查询
db.comment.find({字段名:{$in:[值1,值2]}}) 或 db.comment.find({字段名:{$nin:[值1,值2]}})# 条件连接查询
db.comment.find({$and:[{条件1},{条件2}]}) 或 db.comment.find({$or:[{条件1},{条件2}]})

二、索引

2.1 概述

        在 MongoDB 中使用索引可以高效地执行查询。如果没有索引,MongoDB 必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

        如果在查询时存在适当的索引,MongoDB 可以使用该索引限制必须检查的文档数。

        索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB 还可以使用索引中的排序返回排序结果。

        MongoDB 索引使用 B 树数据结构(确切的说是 B-TreeMySQL B+Tree

2.2 索引的类型

2.2.1 单字段索引

        MongoDB 支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引。

        对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为 MongoDB 可以在任何方向上遍历索引。

2.2.2 符合索引

        MongoDB 还支持多个字段的用户定义索引,即复合索引。

        复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按 userid 正序排序,然后在每个 userid 的值内,再在按 score 倒序排序。

2.2.3 其他索引

1):地理空间索引(Geospatial Index)

        为了支持对地理空间坐标数据的有效查询,MongoDB 提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。

2:)文本索引(Text Indexes)

        MongoDB 提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如 “the”、“a”、“or”),而将集合中的词作为词干,只存储根词。

3:)哈希索引(Hashed Indexes)

        为了支持基于散列的分片,MongoDB 提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。

2.3 索引的操作

2.3.1 查看索引

# 返回一个集合中的所有索引的数组
# MongoDB 3.0+ 版本以上支持
db.collection.getIndexes()
# 查看 comment 集合中所有的索引情况
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "test.comment"}
]

        结果中显示的是默认 _id 索引。

        默认 _id 索引:MongoDB 在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 _id_ ,该索引可防止客户端插入两个具有相同值的文档,您不能在 _id 字段上删除此索引。

        注意:该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键。 

2.3.2 创建索引

# 在集合上创建索引
db.collection.createIndex(keys, options)

Parameter

Type

Description

keys

document

包含字段和值对的文档,其中字段是索引键,值描述该字段的索引类型。对于字段上的升序索引,请指定值1;对于降序索引,请指定值-1。比如: {字段:1或-1} ,其中1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。另外,MongoDB 支持几种不同的索引类型,包括文本、地理空间和哈希索引。

options

document

可选。包含一组控制索引创建的选项的文档。有关详细信息,请参见选项详情列表。

        options(更多选项)列表

Parameter

Type

Description

background

Boolean

建索引过程会阻塞其它数据库操作,background 可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。

unique

Boolean

建立的索引是否唯一。指定为 true 创建唯一索引。默认值为false.

name

string

索引的名称。如果未指定,MongoDB 的通过连接索引的字段名和排序顺序生成一个索引名称。

dropDups

Boolean3.0+ 版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false

sparse

Boolean对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为 true 的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false

expireAfterSeconds

integer

指定一个以秒为单位的数值,完成 TTL 设定,设定集合的生存时间。

v

index version

索引的版本号。默认的索引版本取决于 mongod 创建索引时运行的版本。

weights

document

索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重

default_language

string

对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语

language_override

string

对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language

提示:

        注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() ,之后的版本使用了 db.collection.createIndex() 方法, ensureIndex()  还能用,但只是 createIndex() 的别名。

# 单字段索引示例,对 userid 字段按升序建立索引
> db.comment.createIndex({userid:1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}
# 查看刚才创建的索引,新创建的索引名称为 userid_1
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "test.comment"},{"v" : 2,"key" : {"userid" : 1},"name" : "userid_1","ns" : "test.comment"}
]
# 复合索引示例,对 userid 和 nickname 同时按降序建立复合索引
> db.comment.createIndex({userid:1,nickname:-1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 2,"numIndexesAfter" : 3,"ok" : 1
}
# 查看刚才创建的索引,新创建的索引名称为 userid_1_nickname_-1
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "test.comment"},{"v" : 2,"key" : {"userid" : 1},"name" : "userid_1","ns" : "test.comment"},{"v" : 2,"key" : {"userid" : 1,"nickname" : -1},"name" : "userid_1_nickname_-1","ns" : "test.comment"}
]

2.3.3 删除索引

        可以移除指定的索引,或移除所有索引

# 指定索引的移除
db.collection.dropIndex(index)# 所有索引的移除
db.collection.dropIndexes()

Parameter

Type

Description

index

string or document指定要删除的索引。可以通过索引名称或索引规范文档指定索引。若要删除文本索引,请指定索引名称。
# 删除 comment 集合中 userid 字段上的升序索引
> db.comment.dropIndex({userid:1})
{ "nIndexesWas" : 3, "ok" : 1 }# 查看是否删除成功
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "test.comment"},{"v" : 2,"key" : {"userid" : 1,"nickname" : -1},"name" : "userid_1_nickname_-1","ns" : "test.comment"}
]
# 删除 comment 集合中所有索引。
> db.comment.dropIndexes()
{"nIndexesWas" : 2,"msg" : "non-_id indexes dropped for collection","ok" : 1
}
# 查看还剩下哪些索引
# _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。
> db.comment.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "test.comment"}
]

2.4 索引的使用

2.4.1 执行计划

        分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。

        那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。语法如下:

db.collection.find(query,options).explain(options)
# 查看根据 userid 查询数据的情况
# 其中:"stage" : "COLLSCAN", 表示全集合扫描
> db.comment.find({userid:"1003"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "COLLSCAN","filter" : {"userid" : {"$eq" : "1003"}},"direction" : "forward"},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "node1","port" : 27017,"version" : "4.0.28","gitVersion" : "af1a9dc12adcfa83cc19571cb3faba26eeddac92"},"ok" : 1
}
>
# 下面对userid建立索引
>  db.comment.createIndex({userid:1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}
# 再次查看执行计划
# 其中:"stage" : "FETCH" 表示基于索引的扫描
> db.comment.find({userid:"1003"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "FETCH","inputStage" : {"stage" : "IXSCAN","keyPattern" : {"userid" : 1},"indexName" : "userid_1","isMultiKey" : false,"multiKeyPaths" : {"userid" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"userid" : ["[\"1003\", \"1003\"]"]}}},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "node1","port" : 27017,"version" : "4.0.28","gitVersion" : "af1a9dc12adcfa83cc19571cb3faba26eeddac92"},"ok" : 1
}

2.4.2 涵盖查询

        当查询条件和查询的投影仅包含索引字段时,MongoDB 直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。

# 只查询 userid 字段
> db.comment.find({userid:"1003"},{userid:1,_id:0})
{ "userid" : "1003" }
{ "userid" : "1003" }
> db.comment.find({userid:"1003"},{userid:1,_id:0}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "PROJECTION","transformBy" : {"userid" : 1,"_id" : 0},"inputStage" : {"stage" : "IXSCAN","keyPattern" : {"userid" : 1},"indexName" : "userid_1","isMultiKey" : false,"multiKeyPaths" : {"userid" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"userid" : ["[\"1003\", \"1003\"]"]}}},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "node1","port" : 27017,"version" : "4.0.28","gitVersion" : "af1a9dc12adcfa83cc19571cb3faba26eeddac92"},"ok" : 1
}

三、实战演练

3.1 需求分析

        某头条的文章评论业务如下:

参考这篇文章实现以下功能

        1):基本增删改查 API

        2):根据文章 id 查询评论

        3):评论点赞

3.2 表结构分析

        数据库:articledb

专栏文章评论

comment

字段名称

字段含义

字段类型

备注

_id

ID

ObjectId 或 String

Mongo的主键的字段

articleid

文章ID

String

content

评论内容

String

userid

评论人ID

String

nickname

评论人昵称

String

createdatetime

评论的日期时间

Date

likenum

点赞数

Int32

replynum

回复数

Int32

state

状态

String

0:不可见;1:可见;

parentid

上级ID

String

如果为0表示文章的顶级评论

3.3 技术选型

3.3.1 mongodb-driver

        mongodb-driver mongo 官方推出的 java 连接 mongoDB 的驱动包,相当于 JDBC 驱动。

3.3.2 SpringDataMongoDB

        SpringData 家族成员之一,用于操作 MongoDB 的持久层框架,封装了底层的 mongodb-driver。我们此次使用这个工具进行开发。

3.4 项目搭建

3.4.1 添加 maven 依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/></parent><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency></dependencies>

3.4.2 创建 application.yml 

spring:# 数据源配置data:mongodb:# 主机地址host: 192.168.229.154# 数据库database: articledb# 默认端口是27017port: 27017# 也可以使用uri连接#uri: mongodb://192.168.40.134:27017/articledb

3.4.3 创建启动类

package cn.article;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ArticleApplication {public static void main(String[] args) {SpringApplication.run(ArticleApplication.class, args);}
}

        启动项目,看是否能正常启动,控制台没有错误。

3.4.4 创建评论实体类

        在 cn.article.po 包下创建创建实体类 Comment ,如下:

package cn.article.po;import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;import java.time.LocalDateTime;
import java.util.Date;/*** @Document(collection="comment")*    把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。*    @Document(collection="mongodb 对应 collection 名")*    若未加 @Document ,该 bean save 到 mongo 的 comment collection*    若添加 @Document ,则 save 到 comment collection*    可以省略,如果省略,则默认使用类名小写映射集合*/
@Document(collection="comment")
// 如果想要添加复合索引,则在类的上面使用 @CompoundIndex 标签,例如:@CompoundIndex( def = "{'userid': 1, 'nickname': -1}")
public class Comment {// @Id为主键标识,该属性的值会自动对应 mongodb 的主键字段 "_id",如果该属性名就叫 “id”,则该注解可以省略,否则必须写@Id// 主键private String id;// @Field 标签的意思是对应 mongodb 的字段的名字,如果一致,则无需该注解@Field("content")// 吐槽内容private String content;// 发布日期private Date publishtime;// 添加了一个单字段的索引@Indexed// 发布人IDprivate String userid;// 昵称private String nickname;// 评论的日期时间private LocalDateTime createdatetime;// 点赞数private Integer likenum;// 回复数private Integer replynum;// 状态private String state;// 上级IDprivate String parentid;// 标题IDprivate String articleid;// setter、getter、toString()
}

说明: 

        索引可以大大提升查询效率,一般在查询字段上添加索引,索引的添加可以通过 Mongo 的命令来添加,也可以在 Java 的实体类中通过注解添加。

1):单字段索引注解 @Indexed

        声明该字段需要索引,建索引可以大大的提高查询效率。

# 使用 mongoDB 命令创建单字段索引
db.comment.createIndex({"userid":1})

2):复合索引注解 @CompoundIndex

        复合索引的声明,建复合索引可以有效地提高多字段的查询效率。

# 使用 mongoDB 命令创建复合索引
db.comment.createIndex({"userid":1,"nickname":-1})

3.4.5 创建评论服务层

        在 cn.article.dao 包下创建接口 CommentRepository,如下:

package cn.article.dao;import cn.article.po.Comment;
import org.springframework.data.mongodb.repository.MongoRepository;// 评论的持久层接口
public interface CommentRepository  extends MongoRepository<Comment,String> {}

        在 cn.article.service 包下创建类 CommentService,如下:

package cn.article.service;import cn.article.dao.CommentRepository;
import cn.article.po.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;// 评论的业务层
@Service
public class CommentService {@Autowiredprivate CommentRepository commentRepository;// 保存评论public void saveComment(Comment comment) {// 如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB 会自动生成主键commentRepository.save(comment);}// 更新评论public void updateComment(Comment comment) {commentRepository.save(comment);}// 根据id删除评论public void deleteCommentById(String id) {commentRepository.deleteById(id);}// 查询所有评论public List<Comment> findCommentList() {return commentRepository.findAll();}// 根据id查询评论public Comment findCommentById(String id) {return commentRepository.findById(id).get();}
}

        新建 Junit 测试类 CommentServiceTest ,测试保存和查询所有,代码如下:

package cn.article.service;import cn.article.ArticleApplication;
import cn.article.po.Comment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.LocalDateTime;
import java.util.List;// 测试评论的业务层
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ArticleApplication.class)
public class CommentServiceTest {@Autowiredprivate CommentService commentService;// 保存一条评论@Testpublic void testSaveComment(){Comment comment=new Comment();comment.setArticleid("100000");comment.setContent("测试添加的数据");comment.setCreatedatetime(LocalDateTime.now());comment.setUserid("1003");comment.setNickname("凯撒大帝");comment.setState("1");comment.setLikenum(0);comment.setReplynum(0);commentService.saveComment(comment);}// 查询所有数据@Testpublic void testFindAll(){List<Comment> list = commentService.findCommentList();System.out.println(list);}// 测试根据id查询@Testpublic void testFindCommentById(){Comment comment = commentService.findCommentById("1");System.out.println(comment);}
}

3.5 实现分页效果

        接下来我们实现一个根据上级 ID 查询文章评论的分页列表的功能,首先在 CommentRepository 类中新增方法定义,如下:

// 根据父 id,查询子评论的分页列表
// 需要注意的是这个方法名是有规定的,必须是 findBy属性名,不是随便起的
Page<Comment> findByParentid (String parentid, Pageable pageable);

        在 CommentService 类中新增方法,如下:

// 根据父id查询分页列表
public Page<Comment> findCommentListPageByParentid(String parentid, int page , int size){return commentRepository.findByParentid(parentid, PageRequest.of(page-1,size));
}

        在 CommentServiceTest 测试类中添加测试代码,如下:

// 测试根据父id查询子评论的分页列表
@Test
public void testFindCommentListPageByParentid(){Page<Comment> pageResponse = commentService.findCommentListPageByParentid("3", 1, 2);System.out.println("----总记录数:"+pageResponse.getTotalElements());System.out.println("----当前页数据:"+pageResponse.getContent());
}

        使用 compass 工具将 comment 里面的数据添加一个 parentid 属性,方便我们进行测试,添加结束后,执行执行方法,结果如下:

3.6 实现评论的点赞

        我们先看一下以下点赞的临时示例代码: CommentService 新增 updateThumbup 方法,如下:

/*** 点赞-效率低* @param id*/
public void updateCommentThumbupToIncrementingOld(String id){Comment comment = CommentRepository.findById(id).get();comment.setLikenum(comment.getLikenum()+1);CommentRepository.save(comment);
}

        以上方法虽然实现起来比较简单,但是执行效率并不高,因为我只需要将点赞数加 1 就可以了,没必要查询出所有字段修改后再更新所有字段。

        我们可以使用 MongoTemplate 类来实现对某列的操作。修改 CommentService 类如下所示:

// 注入MongoTemplate
@Autowired
private MongoTemplate mongoTemplate;/*** 点赞数+1* @param id*/
public void updateCommentLikenum(String id){// 查询对象Query query=Query.query(Criteria.where("_id").is(id));// 更新对象Update update=new Update();// 局部更新,相当于$set// update.set(key,value)// 递增$inc// update.inc("likenum",1);update.inc("likenum");//参数1:查询对象;参数2:更新对象;参数3:集合的名字或实体类的类型Comment.classmongoTemplate.updateFirst(query,update,"comment");
}

        在 CommentServiceTest 测试类中添加测试代码,如下:

/*** 点赞数+1*/
@Test
public void testUpdateCommentLikenum(){//对3号文档的点赞数+1commentService.updateCommentLikenum("4");
}

        执行测试用例即可。

相关文章:

MongoDB 索引和常用命令

一、基本常用命令 1.1 案例需求 存放文章评论的数据存放到 MongoDB 中&#xff0c;数据结构参考如下&#xff0c;其中数据库为 articledb&#xff0c; 专栏文章评论 comment 字段名称 字段含义 字段类型 备注 _id ID ObjectId或String Mongo的主键的字段 articlei…...

【超详细】win10安装docker

win10安装docker 因为要在win10复现一个CVE漏洞&#xff0c;需要用到docker所以特地自己亲自安装了一下&#xff0c;其实在win10上安装docker与在Linux上面的原理一致&#xff0c;都是将docker安装在虚拟机里&#xff0c;不同的是win10是安装在Hyper-V虚拟机上的&#xff0c;需…...

JVM调优(一)

什么时候会有内存泄漏&#xff0c;怎么排查&#xff1f; 答&#xff1a; 首先内存泄漏是堆中的一些对象不会再被使用了&#xff0c;但是无法被垃圾收集器回收&#xff0c;如果不进行处理&#xff0c;最终会导致抛出 java.lang.OutOfMemoryError 异常。 内存泄露&#xff1a; …...

Parallels Desktop 19中文-- PD19最新安装

Parallels Desktop 19可以让我们在Mac电脑上运行Windows和其他操作系统&#xff0c;而无需重启计算机。这款软件的稳定性较高&#xff0c;能够在Mac上同时运行多个操作系统&#xff0c;如Windows、Linux等&#xff0c;而无需重启电脑。它可以让用户无缝地在不同操作系统之间切换…...

【c++】向webrtc学比较1:AheadOf、IsNewerTimestamp

webrtc源码分析-rtp序列号新旧比较 大神文章分析的非常到位。大神分析:AheadOrAt(a, b)是判断a是否比b新的核心,其原理是这样的:rfc1982规定了序列号递增间隔不能超过取值范围的1/2(这是自己理解的),那么要判断a是否比b新,只要判断b到a的递增是否在1/2即可,递增超过1/2,…...

华为云云耀云服务器L实例评测|企业项目最佳实践之docker部署及应用(七)

华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践系列&#xff1a; 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测&#xff5c;企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测&#xff5…...

MAC上使用Wireshark常见问题

文章目录 介绍正文启动异常-Permission denied解决方法 过滤协议和地址指定源地址和目的地址调整 time format 介绍 简单记录Wireshark在日常使用过程中的遇到的小case。 正文 Wireshark相较于tcpdump使用较为简单&#xff0c;交互也更为友好。 点击Start即可启动抓包 启动…...

在C++中++a和a++有什么区别?

2023年10月16日&#xff0c;周一中午 a和a在语义上的区别 a是先进行运算(增加1),然后返回新值。 a是先返回原值,然后进行运算(增加1)。 a和a在效率上的区别 a直接返回新值,不需要临时变量保存原值。 而a需要先返回原值,然后再进行增加1的操作。这需要使用一个临时变量来保存…...

NewStarCTF2023公开赛道-压缩包们

题目提示是压缩包 用010editor打开&#xff0c;不见PK头&#xff0c;补上50 4B 03 04 14 00 00 00 将文件改成.zip后缀&#xff0c;打开&#xff0c;解压出flag.zip 尝试解压&#xff0c;报错 发现一串base64编码 SSBsaWtlIHNpeC1kaWdpdCBudW1iZXJzIGJlY2F1c2UgdGhleSBhcmUgd…...

oracle数据库增加表空间数据文件

查询数据文件&#xff1a;select * from dba_data_files order by file_name; 增加&#xff1a;alter tablespace 数据库名 add datafile data size 34359721984;...

【08】基础知识:React中收集表单数据(非受控组件和受控组件)

一、概念 非受控组件&#xff1a; 页面中所有输入类的 DOM&#xff0c;现用现取。 给组件绑定 ref 属性&#xff0c;在需要时通过 ref 获取相应值。 受控组件&#xff1a; 页面中所有输入类的 DOM&#xff0c;随着输入&#xff0c;将内容维护到状态 state中&#xff0c;当…...

数据结构之堆排序和前,中,后,层序遍历,链式二叉树

首先我们要知道升序我们要建小堆&#xff0c;降序建大堆&#xff0c;这与我们的大多人直觉相违背。 因为我们大多数人认为应该将堆顶的数据输出&#xff0c;但如果这样就会导致堆顶出堆以后&#xff0c;堆结构会被破坏&#xff0c;显然我们不能这样。 所有我们反其道而行&…...

多线程中ThreadPoolExecutor.map()中传递多个参数

with concurrent.futures.ThreadPoolExecutor(max_threads) as executor:results executor.map(get_captcha_image, ip_addrs, [img_url] * len(ip_addrs)) #要传入多个参数时&#xff0c;每个参数都得是固定相同长度的可迭代对象# 收集结果for result in results:print(resul…...

linux centos7 环境下 no such file or directory

目录 1.问题描述2.主要原因2.1修改后代码2.2修改前代码 总结参考 1.问题描述 预览excel文件时无法找到对应的html文件 2.主要原因 异常原因&#xff1a;代码获取的是系统的tmp文件&#xff0c;但是linux环境环境中心tmp目录是没有权限的&#xff0c;所以不能获取系统的根目录…...

Nginx 反向代理 SSL 证书绑定域名

配置 Nginx 反向代理和 SSL 泛域名证书绑定域名 Nginx 是一个功能强大的 Web 服务器和反向代理服务器&#xff0c;可以用于将客户端请求转发到后端服务器&#xff0c;并提供安全的 HTTPS 连接。本文将介绍如何配置 Nginx 反向代理&#xff0c;并使用 SSL 泛域名证书绑定域名&a…...

SpringBoot 集成 JMS 与 IBMMQ 代码示例教程

文章目录 前言一、集成 JMS 与 IBMMQ1、pom 依赖2、yml 配置3、Properties 配置类4、Factory 连接工厂类5、配置连接认证6、配置缓存连接工厂7、配置事务管理器8、配置JMS模板9、消息发送与接收 总结 前言 SpringBoot 集成 IBMMQ&#xff0c;实现两个服务间的消息通信。 一、集…...

大模型之Prompt研究和技巧

大模型之Prompt研究和技巧 大模型之Prompt编写简介组成技术Zero-ShotFew-shotCOTCOT-SCTOTGoTReAct 大模型之Prompt编写 简介 Prompt是是给 AI **模型的指令&#xff0c;**一个简短的文本输入&#xff0c;用于引导AI模型生成特定的回答或执行特定任务。 Prompt是你与语言模型沟…...

掌握Golang匿名函数

一个全面的指南&#xff0c;以理解和使用Golang中的匿名函数 Golang以其简单和高效而闻名&#xff0c;赋予开发人员各种编程范式。其中一项增强代码模块化和灵活性的功能就是匿名函数。在这篇正式的博客文章中&#xff0c;我们将踏上探索Golang匿名函数深度的旅程。通过真实世…...

HarmonyOS云开发基础认证---练习题二

【判断题】 2/2 Serverless是云计算下一代的默认计算范式。 正确(True) 【判断题】 2/2 接入认证服务后&#xff0c;用户每次收到验证码短信都需要开发者买单。 错误(False) 【判断题】 2/2 认证服务手机号码登录需要填写国家码。 正确(True) 【判断题】 2/2 在Cloud Functi…...

ffmpeg视频解码器的配置选项含义

lowres的含义 lowres是AVCodecContext结构体中的一个成员变量&#xff0c;用于指定编解码器的降低分辨率级别。 在某些情况下&#xff0c;为了加快编解码的速度或减少计算资源的消耗&#xff0c;可以通过设置lowres参数来降低编解码器的分辨率级别。这将导致编解码器在处理视…...

enter ubuntu boot option in virt-manager

在全屏模型下&#xff0c;启动过程中按下F8或者Ctrl F8。 参考&#xff1a;https://serverfault.com/questions/463024/how-do-i-access-the-f8-bootmenu-while-booting-a-windows-2008r2-kvm-guest-vm...

电商运营该如何做 AB 测试

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 近年&#xff0c;电商行业进入了一个新的发展阶段&#xff0c;一方面电商市场规模持续扩大&#xff0c;另一方面直播电商、即时零售、社区团购等新兴电商业态在疫情…...

go环境部署

#env 命令查看 PATH 发现 #这两条环境变量是把 通过brew 安装的所有程序加入到环境变量中,其中就包含了go /opt/homebrew/sbin /opt/homebrew/bin#mac 系统 将原本 brew 安装的 go 1.20.5版本卸载 brew uninstall go #然后 去官网下载 https://go.dev/dl/ 想要的版本 1.21.0 …...

HTTP/2 中的漏洞

另一个热门漏洞是 CVE-2023-44487。 该漏洞与 HTTP/2 协议实施中的一个缺陷有关&#xff0c;可用于实施 DDoS 攻击。使用该漏洞的攻击被命名为 HTTP/2 快速重置。 为什么它很危险 要利用该漏洞&#xff0c;攻击者需要在 HTTP/2 会话中打开大量请求&#xff0c;然后在不等待服…...

智能油烟机 优化烹饪体验

如果说空调是夏天最伟大的发明&#xff0c;那么油烟机则是健康厨房的伟大推进者。随着科技的发展&#xff0c;智能化的油烟机逐渐走进了人们的日常生活。每当我们在爆炒、油炸食物的时候&#xff0c;油烟总能呛得人眼睛痛、鼻子难受&#xff0c;传统的油烟机面前我们还需要手动…...

啥?PS一秒成图?Adobe的逆天黑科技大公开

在日前举行的 Adobe MAX 创意大会上&#xff0c;Adobe Adobe Firefly Image 2&#xff08;萤火虫二代成像模型&#xff09;、Firefly Vector Model&#xff08;萤火虫矢量模型&#xff09;和Firefly Design Model&#xff08;萤火虫设计模型&#xff09;。 Firefly矢量模型是世…...

扫描器(xray和bp联动)

文章目录 分类主动扫描和被动扫描bp与xray联动 分类 扫描器分为对web的扫描器和对主机的扫描器 主动扫描和被动扫描 主动扫描&#xff1a; 输入某个URL&#xff0c;然后由扫描器中的爬虫模块爬取所有链接&#xff0c;对GET、POST等请求进行参数变形和污染&#xff0c;进行重放测…...

[C++]:1.初识C++和C语言缺陷补充。

初识C和C语言缺陷补充 一.主要内容&#xff1a;二.具体内容&#xff1a;一&#xff1a; 作用域1.命名空间&#xff1a;2.函数声明和定义&#xff1a;3.不存在命名冲突的情况&#xff1a; 二.输入输出&#xff1a;1.基本输入输出&#xff1a;2.关于std的展开&#xff1a; 三.函数…...

BUUCTF学习(三): PHP 代码审计

1、介绍 2、解题 (1)查看网页源代码 (2)返回链接 (3)代码审计...

推荐《Blue prison》

电视动画片《蓝色监狱》改编自金城宗幸原作、野村优介作画的同名漫画作品&#xff0c;于2021年7月31日宣布电视动画化的消息 [1]。该片由8Bit负责动画制作&#xff0c;于2022年10月9日起播出 [2]&#xff0c;全24集。 该作评为Anime Corner 2022年年度体育动画 [24]&#xff0…...

goland安装教程

安装版本&#xff1a; goland-2023.2.3.exe...

java中okhttp和httpclient那个效率高

在比较OkHttp和HttpClient的效率时&#xff0c;需要考虑多个因素&#xff0c;包括性能、吞吐量、资源消耗等。这些因素往往取决于具体的使用场景和需求。 OkHttp是一个由Square开发的现代化HTTP客户端库&#xff0c;它在Android平台上广泛使用&#xff0c;并且也可以在Java应用…...

内存占用问题

虚拟内存介绍 虚拟内存就是将部分磁盘变成内存的拓展&#xff0c;用上去就好像是将内存变大了一样。 比如同样是16G的物理内存&#xff0c;有人能比你多开几个应用&#xff0c;你开两三个就要黑屏&#xff0c;然后浏览器说你内存不够。 打开任务管理器&#xff0c;内存也没有…...

代码随想录二刷 Day 34

455.分发饼干 这个题差不多是两个for循环遍历&#xff0c;然后用双指针法化简&#xff0c;自己可以大概写出来&#xff0c;漏了一个边界条件 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end(…...

软件开源快速开发框架:降本增效,助力流程化办公!

随着时代的进步和社会的发展&#xff0c;应用软件开源快速开发框架的优势特点&#xff0c;可以让不少客户朋友顺利实现流程化办公&#xff0c;朝着数字化方向迈进。流辰信息是专业研发低代码技术平台的服务商&#xff0c;一直在低代码平台领域深耕细作&#xff0c;努力钻研&…...

Flink on k8s容器日志生成原理及与Yarn部署时的日志生成模式对比

Flink on k8s部署日志详解及与Yarn部署时的日志生成模式对比 最近需要将flink由原先部署到Yarn集群切换到kubernetes集群&#xff0c;在切换之后需要熟悉flink on k8s的运行模式。在使用过程中针对日志模块发现&#xff0c;在k8s的容器中&#xff0c;flink的系统日志只有jobma…...

AD20绘制电路板的外形

今天学习了绘制电路板外形的方法&#xff0c;记录一下&#xff0c;回头忘了还能在看看&#xff0c;便能很快的回忆起来了&#xff0c;比看视频啥的要高效的多。毕竟是自己写的&#xff0c;印象要深刻的多。 首先新建一个PCBDoc文件&#xff0c;方法如下图&#xff1a; 在新建的…...

linux 设置开机启动

1、Fedora 20系列操作系统 touch /etc/rc.d/rc.local chmod x /etc/rc.d/rc.local vi /etc/rc.d/rc.local 按“i”进入编辑模式&#xff0c;在文件末尾补充如下内容&#xff1a; 可以根据需要添加你要开机自启动的脚本命令&#xff08;下面是举例&#xff09;&#xff1a; …...

IDEA实现远程Debug调试

一、 前提   需要准备JDK1.8环境&#xff0c;安装IDEA(版本不限) 二、 IDEA中如何实现远程Debug模式 (1)、创建demo项目 1.File一>New一>project… 2.Maven Archetype一>填写Name一>选择jdk1.8一>选择Web一>创建 (2)、配置Idea 找到Remote Jvm Debug java…...

SpringBoot项目入门: IDEA 创建SpringBoot项目

方式1:在线创建项目 https://start.spring.io/ 环境准备 &#xff08;1&#xff09;JDK 环境必须是 1.8 及以上&#xff0c;传送门&#xff1a;jdk1.8.191 下载&#xff08;2&#xff09;后面要使用到 Maven 管理工具 3.2.5 及以上版本&#xff08;3&#xff09;开发工具建议…...

Vue2+SpringBoot实现数据导出到csv文件并下载

前言 该功能用于导出数据到csv文件&#xff0c;并且前端进行下载操作。涉及到java后端以及前端。后端获取数据并处理&#xff0c;前端获取返回流并进行下载操作。csv与excel文件不大相同。如果对导出的数据操作没有很高要求的话&#xff0c;csv文件就够了。具体差异自行百度。我…...

NewStarCTF2023week2-base!(base低位隐写)

附件内容是很多的base64编码的字符串 常见的Base64隐写一般会给一个txt文本文档&#xff0c;内含多个经过base64编码的字符串。解码规则是将所有被修改过的base64字符串结尾的二进制值提取出来组成一个二进制串&#xff0c;以8位分割并转为十进制值&#xff0c;最终十进制对应的…...

众和策略:国际油价走高,石油板块强势拉升,通源石油、和顺石油等涨停

石油板块16日盘中大幅拉升&#xff0c;到发稿&#xff0c;通源石油、和顺石油、贝肯动力、中曼石油、泰山石油、仁智股份等涨停&#xff0c;潜能恒信、博迈科涨约8%。 燃气板块亦上扬&#xff0c;到发稿&#xff0c;洪通燃气、美能动力涨约5%&#xff0c;新疆火炬、九丰动力涨…...

C++笔记之获取线程ID以及线程ID的用处

C笔记之获取线程ID以及线程ID的用处 code review! 文章目录 C笔记之获取线程ID以及线程ID的用处一.获取ID二.线程ID的用处2.1.线程池管理2.2.动态资源分配2.3.使用线程同步机制实现互斥访问共享资源2.4.使用线程 ID 辅助线程同步2.5.任务分发&#xff1a;线程ID可以用于将任务…...

机器人硬件在环仿真:解决实体开发与测试挑战,提升效率与安全性

工业机器人具备出色的灵活性和运动能力&#xff0c;广泛应用于工业制造领域。它们可以完成装配、焊接、喷涂、搬运、加工、品质检测等任务&#xff0c;提高了生产效率&#xff0c;保证了产品质量。此外&#xff0c;在医疗领域也有辅助手术等特殊应用&#xff0c;展现了其在多个…...

stream()

stream().map&#xff0c;stream().filter&#xff0c;stream().peek 1、stream().map&#xff1a;该方法用于将一个流中的元素通过指定的函数进行映射&#xff0c;最终生成一个新的流。例如&#xff0c;如果我们有一个存储了字符串的列表&#xff0c;可以使用 map 方法将列表…...

VBA之正则表达式(43)-- 从网页中提取指定数据

实例需求&#xff1a;由网页中提取下图中颜色标记部分内容&#xff0c;网页中其他部分与此三行格式相同。 方法1 Sub Demo()Dim objRegex As ObjectDim inputString As StringDim objMatches As ObjectDim objMatch As ObjectSet objRegex CreateObject("VBScript.RegEx…...

Elucidating the Design Space of Diffusion-Based Generative Models 阅读笔记

文章使用模块化&#xff08;modular&#xff09;的思想&#xff0c;分别从采样、训练、score network设计三个方面分析和改进diffusion-based models。 之前的工作1已经把diffusion-based models统一到SDE或者ODE框架下了&#xff0c;这篇文章的作者同样也从SDE和ODE的角度出发…...

计算机网络 | 传输层

计算机网络 | 传输层 计算机网络 | 传输层功能概述 参考视频&#xff1a;王道计算机考研 计算机网络 参考书&#xff1a;《2022年计算机网络考研复习指导》 计算机网络 | 传输层 功能概述 传输层是主机才有的层次。 复用&#xff1a;发送方的不同应用进程都可以使用同一个传…...

Android 13 隐私权限和安全变更之通知

介绍 根据官网https://developer.android.com/about/versions/13/summary?hlzh-cn展示的Android 13 功能和变更列表中提及的&#xff0c;Android 13&#xff08;API 级别 33&#xff09;引入了新的权限POST_NOTIFICATIONS。 使用 在Android 13及以上版本&#xff0c;如需向…...