MongoDB基本操作-更新文档

Posted Buddy Yuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB基本操作-更新文档相关的知识,希望对你有一定的参考价值。

  文档插入之后,我们就可以使用update方法来进行更新。在Mongo Shell里面主要提供下面三种方法进行更新:l db.collection.updateOne(<filter>, <update>, <options>)

l db.collection.updateMany(<filter>, <update>, <options>)

l db.collection.replaceOne(<filter>, <replacement>, <options>)

而具体的操作在于修改器。下面我们来一一介绍。

1. $inc

这个操作符是专门用来增加或者减少数字的。$inc操作符接受正值和负值。如果字段不存在,$inc将创建字段并将该字段设置成指定的值。而如果一个字段已经存在且是空值,使用$inc操作符将产生错误。

例如:先插入ID1的测试数据。然后修改quantitymetrics.orders

>db.example.insertOne({_id:1,sku: "abc123",quantity: 10,metrics: {orders: 2,ratings: 3.5} })

>db.example.updateOne({_id:1},{$inc:{quantity:-2, "metrics. orders":1} })

{"acknowledged" : true, "matchedCount" : 1,"modifiedCount" : 1 }

操作成功之后会提示匹配行数和修改行数。这里我们主要通过主键来匹配。如果这里传入的是字符串,就会报错,指出非数字类型错误。WriteError: Cannot increment with non-numeric argument: {quantity:"-2"}

>db.example.updateOne({_id:1},{$inc:{quantity:"-2"} })

2017-09-29T12:05:59.704+0800E QUERY [thread1] WriteError: Cannot increment with non-numeric argument:{quantity: "-2"} :

如果一个字段不存在,$inc操作符将直接创建它。

>db.example.updateOne({_id:1},{$inc:{score:10}})

{"acknowledged" : true, "matchedCount" : 1,"modifiedCount" : 1 }

>db.example.find()

{"_id" : 1, "sku" : "abc123", "quantity": 8, "metrics" : { "orders" : 2, "ratings" : 3.5," orders" : 1 }, "score" : 10 }

如果一个已经存在空值,用$inc操作将产生错误。这里指出Cannotapply $inc to a value of non-numeric type

>db.example.insertOne({_id: 2,sku: null});

>db.example.updateOne({_id:1},{$inc:{sku:10}})

2017-09-29T17:13:22.754+0800E QUERY    [thread1] WriteError: Cannotapply $inc to a value of non-numeric type. {_id: 1.0} has the field 'sku' ofnon-numeric type string

2.$min

Min操作符,只有当指定的值小于现有的值时,才会进行更新。

>db.example.insertOne({_id: 1,highScore: 800, lowScore: 200 });

>db.example.update({_id:1},{$min:{lowScore:150}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.example.find()

{"_id" : 1, "highScore" : 800, "lowScore" : 150 }

如果我们$min指定的值大于文档的值,是没有效果的。这里提示nModified0

>db.example.update({_id:1},{$min:{lowScore:250}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 0})

如果该字段不存在,则min将该字段设置成指定的值。

>db.example.update({_id:1},{$min:{midScore:250}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.example.find()

{"_id" : 1, "highScore" : 800, "lowScore" : 150,"midScore" : 250 }

可以看出,我们的$min操作符其实是在做比较,比较值的大小之后然后进行更新,同样我们也可以比较日期型。

>db.person.find()

{"_id" : 1, "birth" :ISODate("2013-09-25T00:00:00Z") }

>db.person.update({_id:1},{$min:{ birth :new Date("2012-09-25")}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

3.$max

Max操作符其实和min类似,只不过正好与Min操作符相反,当指定的值大于文档中的值时,则进行更新。

当然这里还需要介绍一个MongoDB当中的BSON类型的比较,默认有以下顺序。从小到大进行排列。

1.     MinKey (internal type)

2.     Null

3.     Numbers (ints, longs, doubles, decimals)

4.     Symbol, String

5.     Object

6.     Array

7.     BinData

8.     ObjectId

9.     Boolean

10.   Date

11.   Timestamp

12.   Regular Expression

13.   MaxKey (internal type)

假设现在文档里面是日期类型,我用数字类型和他进行比较,比如$max,会发生什么呢?可以发现案例中birth并不会改变,因为类型3小于类型10。而我们使用$min操作符的时候,就会发生修改。因为类型310要小。

>db.person.updateOne ({_id:1},{$max:{birth:9}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 0})

>db.person.find()

{"_id" : 1, "birth" :ISODate("2013-09-25T00:00:00Z")

>db.person.updateOne ({_id:1},{$min:{birth:9}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.person.find()

{"_id" : 1, "birth" : 9 }

4. $mul

这个操作符的含义是将文档中的值乘以指定的数字。如果文档中不存在空值,$mul将创建该字段,并赋值为0。

>db.active.insertOne({_id: 1,num: 1.5});

>db.active.updateOne({_id:1},{$mul:{num:1.5} })

>db.active.find()

{"_id" : 1, "num" : 2.25 }

>db.active.updateOne({_id:1},{$mul:{num2:1.7} })

>db.active.find()

{"_id" : 1, "num" : 2.25, "num2" : 0 }

当你的操作使用不同的类型的值,会发生数字类型的转换。有下面的规则。


32-bit Integer

64-bit Integer

Float

32-bit Integer

32-bit or 64-bit Integer

64-bit Integer

Float

64-bit Integer

64-bit Integer

64-bit Integer

Float

Float

Float

Float

Float

32位整型和32位整型操作,结果为是32位整型或者是64位整型。这是因为相乘的数字超过了32位最大值。MongoDB Shell环境中默认使用64位浮点型数据。而NumberInt()方法构造的是32位整型数据。NumberLong()方法构造的是64位整型数据。

我们来测试一下,不同类型之间的转换,比如我用32位整型和64位整型做$mul操作,最后结果会是64位整型。

db.active.insertOne({_id:2,num: NumberInt(20)});

>db.active.updateOne({_id: 2},{$mul:{num: NumberLong(10)}});

{"acknowledged" : true, "matchedCount" : 1,"modifiedCount" : 1 }

>db.active.find()

{"_id" : 2, "num" : NumberLong(200) }

5.$rename

$rename操作符可以更新字段的名称。新的字段必须与现有的字段不同。$rename操作符首先把旧字段执行$unset操作,然后对新字段执行$set操作,因此操作可能不会保留文档中字段的顺序。重命名的字段在文档中可能会发生移动。

如果要rename的字段不在文档当中,则$rename不会执行任何操作。

>db.students.insertOne({_id: 1,name: "Buddy Yuan"});

{"acknowledged" : true, "insertedId" : 1 }

>db.students.update({},{$rename:{"name":"fname"}});

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.students.find();

{"_id" : 1, "fname" : "Buddy Yuan" }

6.$set

$set操作符将替换文档中指定字段的值。如果该字段不存在,$set将添加一个指定字段并赋值。但是还有一个前提,新字段不能违反字段类型的约束。

>db.students.find()

{"_id" : 1, "name" : "Buddy Yuan" }

>db.students.update({_id: 1 },{ $set:{name: "Buddy"}});

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.students.find()

{"_id" : 1, "name" : "Buddy" }

字段不存在的情况。

>db.students.update({_id: 1 },{ $set:{fname: "Buddy"}});

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.students.find()

{"_id" : 1, "name" : "Buddy Yuan","fname" : "Buddy" }

7.$unset

$unset操作符可以把文档中的字段完全删除。

>db.students.update({_id: 1 },{ $unset:{fname:""} });

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.students.find()

{"_id" : 1, "name" : "Buddy Yuan" }

8.$setOnInsert

当文档中没有字段的时候。update方式使用upset选项的时候,将会执行insert操作。$setOnInsert操作符会给指定的字段赋值。

>db.products.update(

...   { _id: 1 }, { $set: { item:"apple" },$setOnInsert: { defaultQty: 100 } },

...   { upsert: true }

...)

WriteResult({"nMatched" : 0, "nUpserted" : 1, "nModified" : 0,"_id" : 1 })

>db.products.find()

{"_id" : 1, "item" : "apple","defaultQty" : 100 }

可以看到集合插入了文档。而一旦文档中包含了这个字段,则$setOnInsert操作符不会在对这个字段做处理,而$set操作符会更新另外一个字段。

>db.products.update(

...   { _id: 1 },{$set: { item: "apple2"},$setOnInsert: { defaultQty: 150 }},

...   { upsert: true }

...)

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.products.find()

{"_id" : 1, "item" : "apple2","defaultQty" : 100 }

9.$current_date

$current_date操作符设置字段值为当前日期。

>db.persons.insert({_id:1,"name":"test","salary":1000,lastModified:new Date('2013/02/22 11:03:38')});

WriteResult({"nInserted" : 1 })

>db.persons.find()

{"_id" : 1, "name" : "test", "salary" :1000, "lastModified" : ISODate("2013-02-22T03:03:38Z") }

>db.persons.update({"_id" : 1},{$currentDate: {lastModified: true}})

WriteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

>db.persons.find()

{"_id" : 1, "name" : "test", "salary" :1000, "lastModified" : ISODate("2017-10-12T15:37:44.596Z")}


以上是关于MongoDB基本操作-更新文档的主要内容,如果未能解决你的问题,请参考以下文章

03 MongoDB文档的各种增加更新删除操作总结

03 MongoDB文档的各种增加更新删除操作总结

MongoDB基本操作-更新文档

MongoDB创建更新删除文档操作

MongoDB - 选择文档进行更新 - 选择后没有其他操作修改同一文档

翻译MongoDB指南/CRUD操作