资料更新(Update)如同写入或删除一样,都是相同 Pattern,差别是条件比较多。
db.collection.updateOne(filter, update, options)
db.collection.updateMany(filter, update, options)
两者基本上是一样的,相信你们看完前面的 insertOne, insertMany, deleteOne, deleteMany 都有感觉了。
filter 是过虑条件,也就是你要找到欲更新文件的条件。
options 这个是更新的设定选项,在刚开始会用不到太多项目,只有一个要特别注意,就是 upsert
,通常我们会设定为 true
,这也是 MongoDB 很方便的地方。顾名思义,就是当欲更新的文件如果存在时,进行 update
,当找不到这比文件时,就进行 insert
。
马上来个范例,我们先查询,确保没有该文件,接着执行 upsert:true
的 updateOne
语法:
film> db.upsert.sample.find()
film> db.upsert.sample.updateOne({},{$set:{'name':'try upsert'}},{upsert:true})
{
acknowledged: true,
insertedId: ObjectId("6131047cf80a26301f6a5856"),
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 1
}
film> db.upsert.sample.find()
[ { _id: ObjectId("6131047cf80a26301f6a5856"), name: 'try upsert' } ]
film>
可以看到 upsert.sample
collection 起初是没有资料的,我使用了 find()
,不带任何参数的查询,查不到任何资料。
接着再一个 updateOne
的内容里,执行後直接新增比资料,透过回传的参数也可以看到 upsertedCount
数量为 1。
insertedId
:本次执行结果,写入的 ObjectId 清单matchedCount
:本次执行结果,符合查询条件的文件数量modifiedCount
:本次执行结果,符合查询条件且更新的文件数量upsertedCount
:本次执行结果,进行 upsert 的文件数量接着将这次的 updateOne 语法来拆开来看:
db.upsert.sample.updateOne(
{},
{$set:{'name':'try upsert'}},
{upsert:true}
)
可以看到三组大括弧 {}
,这分别对应了上面提到的 filter
, update
与 options
。
filter
:这边我们直接不带条件,想进行全部文件的 updateupdate
:我们设定 name 栏位的值为 try upsert,$set 是 MongoDB 的 operator 之一,这个我们之後再讲解,先忍着略过它。options
:这次 updateOne 中,设定值设定 upsert
为 true
,代表找不到资料就写入。设定还有 writeConcern
, collation
和 hint
等,这个会在後面再讲解,现在提就太深入了。这次我们准备几笔符合查询条件的文件,使用 UpdateOne
看看会发生什麽事情。
资料库内有三笔名为 Arthas
的资料
film> db.upsert.demo2.find()
[
{ _id: ObjectId("61310798630faf5d23c909d3"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]
执行 updateOne,将名为 Arthas
的资料栏位改为 ErrorName
film> db.upsert.demo2.updateOne({'name':'Arthas'}, {$set:{'name':'ErrorName'}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
film> db.upsert.demo2.find()
[
{ _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
{ _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]
可以看到执行後,再次查询,只会有第一笔被修改,因为我们执行的是 updateOne
。
那为什麽第一笔不是_id
为9d4
或 9d5
结尾的资料呢?因为 MongoDB 采用的是 natural sort
,在这个情况下就是 9d3
这一笔。我们会在後面的天数讲到 natural sort
,这是一个非重要的概念。
replaceOne,找到符合条件的文件,直接整份文件取代。
replaceOne 用法与 Update 高度相近,来看看它的长相:
db.collection.replaceOne(filter, replacement, options)
我们来尝试找到一个文件,{name:'Thrall'}
,将它改成下面这样子
{
'name':'NewThrall',
'type':'melee'
}
film> db.upsert.demo2.find()
[
{ _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
{ _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d6"), name: 'Thrall' }
]
film> db.upsert.demo2.replaceOne({'name':'Thrall'}, {'name':'NewThrall', 'type':'melee'})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
film> db.upsert.demo2.find()
[
{ _id: ObjectId("61310798630faf5d23c909d3"), name: 'ErrorName' },
{ _id: ObjectId("61310798630faf5d23c909d4"), name: 'Arthas' },
{ _id: ObjectId("61310798630faf5d23c909d5"), name: 'Arthas' },
{
_id: ObjectId("61310798630faf5d23c909d6"),
name: 'NewThrall',
type: 'melee'
}
]
可以看到新的内容已经取代上去,特别要注意的是 _id 并没有任何异动,即便它不是客制化的 _id
,仍然不会改变,因为这个操作是取代文件内容,不会影响它本身的 key。
附带一提,replaceOne 如同上面所说,设定值是几乎一样的,所以也有 upsert 功能,这边就不再示范了,结果会与 update 一样。
本系列文章会同步发表於我个人的部落格 Pie Note
终於到了我们的元件篇啦!!! 今天是第一个元件,所以稍微简单一点。 我们要来做下载的进度条~ 前置...
接下来研究NoSQL的查询方式, 最好有大量范例资料使用. 可利用AWS的范例快速新增. 可先到此下...
还记得一开始建立专案时选择的是 Angular + Nestjs 作为专案的前後端语言吗? 什麽是 ...
前言 在前一章节中,使用了ssh-keygen来演示如何使用金钥交换的方式进行验证,在本章节中,将会...
Grid是什麽 Grid是砖墙式版面,使用二维的排版方式,与flexbox不同的地方是Grid一次可...