目录
1 文档DML
主要讲解的是文档的创建,更新,删除等相关操作
1.1 定义
文档是一组键值(key-value
)对(即 BSON
)。MongoDB
的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB
非常突出的特点
下表列出了 RDBMS 与 MongoDB 对应的术语:
RDBMS | MongoDB |
---|---|
数据库 | 数据库 |
表格 | 集合 |
行 | 文档 |
列 | 字段 |
表联合 | 嵌入文档 |
主键 | 主键 (MongoDB 提供了 key 为 _id ) |
需要注意的是:
- 文档中的
键/值
对是有序的。 - 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
MongoDB
区分类型和大小写。MongoDB
的文档不能有重复的键。- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
- 键不能含有
\0
(空字符)。这个字符用来表示键的结尾。 .
和$
有特别的意义,只有在特定环境下才能使用。- 以下划线
_
开头的键是保留的(不是严格要求的)
1.2 插入文档
由于文档的数据结构和JSON
基本一样。所有存储在集合中的数据都是 BSON
格式。BSON
是一种类似 JSON
的二进制形式的存储格式,是 Binary JSON
的简称。
MongoDB
使用 insert()
或 save()
方法向集合中插入文档,语法如下:
db.COLLECTION_NAME.insert(document)
或
db.COLLECTION_NAME.insertOne(document)
或
db.COLLECTION_NAME.insertMany(document)
或
db.COLLECTION_NAME.save(document)
save()
:如果_id
主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用db.collection.insertOne()
或db.collection.replaceOne()
来代替。
如果不指定_id
字段save()
方法类似于insert()
方法。如果指定_id
字段,则会更新该_id
的数据insert()
: 若插入的数据主键已经存在,则会抛org.springframework.dao.DuplicateKeyException
异常,提示主键重复,不保存当前数据。3.2 版本之后新增了db.collection.insertOne()
和db.collection.insertMany()
。db.collection.insertOne()
用于向集合插入一个新文档db.collection.insertMany()
用于向集合插入一个多个文档,语法格式如下:
插入语法格式:
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
参数说明:
document
:要写入的文档。writeConcern
:写入策略,默认为 1,即要求确认写操作,0 是不要求。ordered
:指定是否按顺序写入,默认true
,按顺序写入。
实例
以下文档可以存储在 MongoDB 的 test数据库 的 col 集合中:
db.test.insert({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'myself',
url: 'http://www.test.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
以上实例中 test
是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。
我们也可以将数据定义为一个变量,如下所示:
document=({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'myself',
url: 'http://www.test.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
});
执行后显示结果如下:
document=({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'myself',
url: 'http://www.test.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
});
执行插入操作:
db.test.insert(document)
WriteResult({ "nInserted" : 1 })
1.3 更新文档
使用 update()
和 save()
方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。
1.3.1 update() 方法
update()
方法用于更新已存在的文档。语法格式如下:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:
query
:update
的查询条件,类似sql update
查询内where
后面的。update
:update
的对象和一些更新的操作符(如$
,$inc
...)等,也可以理解为sql update
查询内set
后面的upsert
: 可选,这个参数的意思是,如果不存在update
的记录,是否插入objNew
,true
为插入,默认是false
,不插入。multi
: 可选,mongodb
默认是false
,只更新找到的第一条记录,如果这个参数为true
,就把按条件查出来多条记录全部更新。writeConcern
:可选,抛出异常的级别。
WriteConcern.NONE
:没有异常抛出
WriteConcern.NORMAL
:仅抛出网络错误异常,没有服务器错误异常
WriteConcern.SAFE
:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
WriteConcern.MAJORITY
: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。
WriteConcern.FSYNC_SAFE
: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
WriteConcern.JOURNAL_SAFE
:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
WriteConcern.REPLICAS_SAFE
:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作
接着我们通过 update() 方法来更新标题(title):
>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) # 输出信息
以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi
参数为 true
>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
附:
db.collection.updateOne()
:向指定集合更新单个文档db.collection.updateMany()
:向指定集合更新多个文档- 只更新第一条记录:
db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );
- 全部更新:
db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );
- 只添加第一条:
db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );
- 全部添加进去:
db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );
- 全部更新:
db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true );
- 只更新第一条记录:
db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );
1.3.2 save() 方法
save()
方法通过传入的文档来替换已有文档,_id
主键存在就更新,不存在就插入。语法格式如下:
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
参数说明:
document
: 文档数据。writeConcern
:可选,抛出异常的级别。
实例
以下实例中我们替换了_id
为56064f89ade2f21f36b03136
的文档数据:
db.col.save({
"_id" : ObjectId("56064f89ade2f21f36b03136"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "myself",
"url" : "http://www.test.com",
"tags" : [
"mongodb",
"NoSQL"
],
"likes" : 110
})
1.3.3 原子操作命令
MongoDB
原子操作常用命令,如:$set
,$unset
,$inc
$set
用来指定一个键并更新键值,若键不存在并新增该字段
{ $set : { field : value } }
$unset
指定key,用来删除一个键。值是多少都不影响。好像并非真的删除,只是把它置为null
{ $unset : { field : 1} }
$inc
$inc
可以对文档的某个值为数字型
(只能为满足要求的数字)的键进行增减
的操作。
{ $inc : { field : value } }
db.test.update({hometown:"蒙古"},{$inc:{age:2}})
age字段自增2$push
在数组末尾
追加一个元素
用法:{ $push : { field : value } }
,会把value
追加到field
里面去,field
一定要是数组类型才行,如果field
不存在,会新增一个数组类型加进去。
db.test.update({hometown:"蒙古"},{$set:{list:[1,2,3,4,5]}})
新增一个列表
db.test.update({hometown:"蒙古"},{$push:{list:6}})
追加元素$pushAll
同$push
,只是一次可以追加多个值到一个数组字段内。
{ $pushAll : { field : value_array } }
$pull
从数组field
内删除一个等于value
值,如果有多个相同元素,会全都被删除
db.test.update({hometown:"蒙古"},{$pull:{list:6}})
$addToSet
增加一个值到数组内,而且只有当这个值不在数组内才增加。$pop
删除数组的第一个
或最后一个元素
,值只能选1
或-1
$rename
修改字段名称
{ $rename : { old_field_name : new_field_name } }
$bit
位操作,integer
类型
{$bit : { field : {and : 5}}}
1.3.4 位置操作符
1.3.4.1 位置操作符$
位置操作符$
,如果不知道数组中元素的位置,可以使用位置$
操作符
位置$
操作符充当更新文档查询中第一个匹配的占位符,即使用了multi:true
也没用
$
可以在不显示指定数组元素位置的情况下标识要更新的数组中的元素,$
只是单个占位符
.$[].
会更新数组内全部元素,可以多个。.$.
只会更新符合查询条件的数组内的元素,有且只能有一个
先查询
t.find()
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
更新
t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
再查询
t.find()
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
1.3.4.2 位置操作符$[]
位置操作符$[]
,要更新数组中的所有元素
查询条件匹配的情况下,$[]
会修改指定数组字段中的所有元素
因为$[]
是修改整个数组
。所以无需在查询条件中指定数组
注:3.6版本后的新功能
语法格式如下:
db.collection.updateMany(
{ <query conditions> },
{ <update operator>: { "<array>.$[]" : value } }
)
案例:
插入
db.stu.insert({_id:1,grades:[80,85,90]})
db.stu.insert({_id:2,grades:[88,90,92]})
db.stu.insert({_id:3,grades:[85,100,90]})
更新:
db.stu.update({grades:85},{$set:{'grades.$[]':'修改'}},{multi:true})
1.3.4.3 位置操作符$[< identifier >]
会使用一个或多个数组作为过滤条件进行匹配
在monodb3.6版本后才可使用
过滤后的位置运算符$[<identifier>]
标识与arrayFilters
条件匹配的数组元素来进行更新操作。
位置$[identifier]
运算符充当数组字段中arrayFilters
中指定条件匹配的所有元素的占位符
语法:
db.collection.update(
{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }
)
或者:
db.collection.update(
{ <query selector> },
{ <update operator>: { "array.$[<identifier>].field" : value } },
{ arrayFilters: [ { <identifier>: <condition> } } ] }
)
注意
:在<identifier>
必须以小写字母开头,并且只包含字母数字字符
1.3.4.4 $elemMatch()
位置操作符$
能够更新第一个匹配的数组元素,但是通过$elemMatch()
操作符匹配多个内嵌文档的查询条件
考虑如下的stu集合文档grades字段是一个嵌套字段的文档
{
_id: 4,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
}
如下语句会更新嵌套文档中的std值为6,条件是文档的主键是4,字段grades的嵌套文档字段grade字段值小于等于90mean字段值大于80
db.students.update(
{
_id: 4,
grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
},
{ $set: { "grades.$.std" : 6 } }
)
1.4 MongoDB 删除文档
MongoDB remove()
函数是用来移除集合中的数据。
MongoDB
数据更新可以使用 update()
函数。在执行 remove()
函数前先执行 find()
命令来判断执行的条件是否正确
db.collection.remove(
<query>,
<justOne>
)
参数说明:
query
:(可选)删除的文档的条件。justOne
: (可选)如果设为true
或1
,则只删除一个文档,如果不设置该参数,或使用默认值false
,则删除所有匹配条件的文档。
但是remove()
方法已经过时了,现在官方推荐使用 deleteOne()
和 deleteMany()
方法。
删除集合下全部文档:
db.test.deleteMany({})
删除 status 等于 A 的全部文档:
db.test.deleteMany({ status : "A" })
删除 status 等于 D 的一个文档:
db.test.deleteOne( { status: "D" } )
标签:1.3,MongoDB,db,update,更新,DML,文档
From: https://www.cnblogs.com/jingzh/p/16860934.html