jlthlx 发表于 2017-12-16 07:34:55

MongoDB学习笔记三

插入insert

单条插入
  

> db.foo.insert({"bar":"baz"})  
WriteResult({
"nInserted" : 1 })  


批量插入
  

> db.foo.insert([{"_id":1},{"_id":2},{"_id":3}])  
BulkWriteResult({
  

"writeErrors" : [ ],  

"writeConcernErrors" : [ ],  

"nInserted" : 3,  

"nUpserted" : 0,  

"nMatched" : 0,  

"nModified" : 0,  

"nRemoved" : 0,  

"upserted" : [ ]  
})
  

> db.foo.find()  
{
"_id" : 1 }  
{
"_id" : 2 }  
{
"_id" : 3 }  

>   

  如果在执行批量插入的过程中有一个文档插入失败,那么在这个文档之前的所有文档都会插入成功,之后的所有全部失败。
  

> db.foo.insert([{"_id":10},{"_id":11},{"_id":10},{"_id":12}])  
BulkWriteResult({
  

"writeErrors" : [  
{
  

"index" : 2,  

"code" : 11000,  

"errmsg" : "E11000 duplicate key error collection: test.foo index: _id_ dup key: { : 10.0 }",  

"op" : {  

"_id" : 10  
}
  
}
  
],
  

"writeConcernErrors" : [ ],  

"nInserted" : 2,  

"nUpserted" : 0,  

"nMatched" : 0,  

"nModified" : 0,  

"nRemoved" : 0,  

"upserted" : [ ]  
})
  

> db.foo.find()  
{
"_id" : 10 }  
{
"_id" : 11 }  

>   


删除文档

remove
  remove函数接受一个查询文档作为参数。符合条件的文档才被删除。删除数据是永久性的,不能撤销,也不能恢复。
  

> db.foo.remove()  

2016-12-15T19:50:31.721+0800 E QUERY    Error: remove needs a query :  
DBCollection.prototype._parseRemove@src
/mongo/shell/collection.js:406:1  
DBCollection.prototype.remove@src
/mongo/shell/collection.js:433:18  
@(shell):
1:1  

  
> db.foo.remove({"_id":10})
  
WriteResult({ "nRemoved" : 1 })
  
> db.foo.find()
  
{ "_id" : 11 }
  
>
  


drop
  要清空整个集合,那么使用drop直接删除集合会更快。代价是:不能指定任何限定条件。整个集合都被删除,所有元数据都不见了。
  

> for(var i=0;i<1000000;i++){  
... db.tester.insert({
"foo":"bar","baz":i,"z":10-i})  
... }
  
WriteResult({
"nInserted" : 1 })  

> db.tester.find()  
{
"_id" : ObjectId("58528543b049609a5fa74f7c"), "foo" : "bar", "baz" : 0, "z" : 10 }  ......
  
Type
"it" for more  

> db.tester.drop()//插入一百万条数据,使用drop删除,只需1ms  

true  
>
  


更新文档update
  Update有两个必须参数:
  一是查询文档,用于定位需要更新的目标文档
  二是修改器文档,用于说明要找到的文档进行哪些修改
  更新操作是不可分割的:若是两个更新同时发生,先到达服务器的先执行,接着执行另一个。
  

db.foo.insert({  
...
"name":"yyb",  
...
"friends":32,  
...
"enemies":2  
... })
  
WriteResult({
"nInserted" : 1 })  

> db.foo.update({"name":"yyb"},{"name":"joe"})//将yyb这个文档修改成{“name”:“joe”}  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.foo.find()  
{
"_id" : ObjectId("58528a2bb049609a5fb691bc"), "name" : "joe" }  

>   


文档替换
  用一个新文档完全替换匹配的文档,这适合大规模模式迁移的情况。
  

db.user.insert({  
... ...
"name":"joe",  
... ...
"friends":32,  
... ...
"enemies":2  
... ... })
  
WriteResult({
"nInserted" : 1 })  

//将上面这个文档的后两个字段移到子文档为realtionships中  
> var joe=db.user.findOne({"name":"joe"})
  
> joe.relationships={"friends":joe.friends,"enemies":joe.enemies};
  
{ "friends" : 32, "enemies" : 2 }
  
> delete joe.friends
  
true
  
> delete joe.enemies
  
true
  
> db.user.update({"name":"joe"},joe);
  
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
  
> db.user.find()
  
{ "_id" : ObjectId("58529188b049609a5fb691bf"), "name" : "joe", "relationships" : { "friends" : 32, "enemies" : 2 } }
  
>
  

  常见的错误是查询条件匹配到了多个文档,然后更新时由于第二个参数的存在就产生重复的 _id 值。数据库会抛出异常。
  

> db.user.find()  
{
"_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 21 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }  

> joe=db.user.findOne({"name":"yyb","age":30})  
{
"_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }  

> joe.age++;  

30  
> db.user.update({"name":"yyb"},joe)
  
WriteResult({
  
"nMatched" : 0,
  
"nUpserted" : 0,
  
"nModified" : 0,
  
"writeError" : {
  
"code" : 16837,
  
"errmsg" : "The _id field cannot be changed from {_id: ObjectId('585295e3b049609a5fb691c5')} to {_id: ObjectId('585295e3b049609a5fb691c6')}."
  
}
  
})
  
>
  


使用修改器
  使用原子性的更新修改器,指定对文档的某些字段进行更新。更新修改器是种特殊的键,用来指定复杂的更新操作,比如修改、添加或者删除键,还可能是操作数组或者内嵌文档。
  

> db.user.find()  
{
"_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 21 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }  

> db.user.update({"name":"yyb"},{$inc:{"age":5}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })> db.user.find({"name":"yyb"})  
{
"_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 26 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }  
{
"_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }  

>   

  明明匹配3条,却只改了一条。原来MongoDB默认只会更新匹配的第一条,如果要更新多条,还得指定参数。
  使用修改器时,_id的值不能改变。(整个文档替换时可以改变“_id”)

$set与$unset
  用来指定一个字段的值。如果这个字段不存在,则创建它。
  

> db.user.insert({  
...
"name":"yyb",  
...
"age":20,  
...
"sex":"male",  
...
"location":"cd"})  
WriteResult({
"nInserted" : 1 })  

>> db.user.update({"name":"yyb"},{"$set":{"email":"123@qq.com"}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.user.find().pretty()  
{
  

"_id" : ObjectId("58529e66b049609a5fb691c9"),  

"name" : "yyb",  

"age" : 20,  

"sex" : "male",  

"location" : "cd",  

"email" : "123@qq.com"  
}
  

>   

  用 $set 甚至可以修改键的类型。用 $unset 可以将键完全删除。
  

>db.user.update(  
... ... {
"name":"yyb"},  
... ... {
"$set":{"email":["xx@qq.com","xl@sina.com"]}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.user.find().pretty()  
{
  

"_id" : ObjectId("58529e66b049609a5fb691c9"),  

"name" : "yyb",  

"age" : 20,  

"sex" : "male",  

"location" : "cd",  

"email" : [  

"xx@qq.com",  

"xl@sina.com"  
]
  
}
  

> db.user.update({"name":"yyb"},{"$unset":{"email":1}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.user.find().pretty()  
{
  

"_id" : ObjectId("58529e66b049609a5fb691c9"),  

"name" : "yyb",  

"age" : 20,  

"sex" : "male",  

"location" : "cd"  
}
  

  也可以用 $set 修改内嵌文档:
  

{  

"_id" : ObjectId("5853e17ff7720722b4ded850"),  

"title" : "a blog post",  

"content" : "...",  

"author" : {  

"name" : "yyb",  

"email" : "aaa@sina.com"  
}
  
}
  

> db.blog.update(  
... {
"author.name":"yyb"},  
... {
"$set":{"author.name":"joe"}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.blog.findOne()  
{
  

"_id" : ObjectId("5853e17ff7720722b4ded850"),  

"title" : "a blog post",  

"content" : "...",  

"author" : {  

"name" : "joe",  

"email" : "aaa@sina.com"  
}
  
}
  

  增加、删除、修改键时,应该使用$开头的修改器,否则可能会将整个文档替换掉。

$inc
  $inc 用来增加已有键的值,或者该键不存在那就创建一个。对于更新分析数据、因果关系、投票或者其他有变化数值的地方很方便。
  

> db.games.insert({"games":"pinball","user":"joe"})  
WriteResult({
"nInserted" : 1 })  

> db.games.update({"games":"pinball"},{"$inc":{"score":50}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.games.findOne()  
{
  

"_id" : ObjectId("5853e517f7720722b4ded851"),  

"games" : "pinball",  

"user" : "joe",  

"score" : 50  
}
  

> db.games.update({"games":"pinball"},{"$inc":{"score":10000}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.games.findOne()  
{
  

"_id" : ObjectId("5853e517f7720722b4ded851"),  

"games" : "pinball",  

"user" : "joe",  

"score" : 10050  
}
  

>  

  $inc 就是专门用来增减数字的。且只能用于整型、长整型或者双精度浮点型的值。其他类型的数据会操作失败。
  

> db.foo.insert({"count":"1"})  
WriteResult({
"nInserted" : 1 })  

  

> db.foo.update({},{"$inc":{"count":1}})  
WriteResult({
  

"nMatched" : 0,  

"nUpserted" : 0,  

"nModified" : 0,  

"writeError" : {  

"code" : 16837,  

"errmsg" : "Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('5853e73df7720722b4ded853')} has the field 'count' of non-numeric type String"  
}
  
})
  

>   

  $inc 键的值必须为数字”,不能使用字符串、数组或者其他非数字的值。要修改其他类型,应该使用 $set 或者数字修改器。
  

> db.foo.insert({"count":1})  
WriteResult({
"nInserted" : 1 })  

  

> db.foo.update({},{"$inc":{"count":"5"}})  
WriteResult({
  

"nMatched" : 0,  

"nUpserted" : 0,  

"nModified" : 0,  

"writeError" : {  

"code" : 14,  

"errmsg" : "Cannot increment with non-numeric argument: {count: \"5\"}"  
}
  
})
  

>   


数组修改器

$push
  $push 添加元素。如果数组已经存在,会向已有的数组末尾加入一个元素,要是没有就创建一个新的数组。
  

> db.blog.post.findOne()  
{
  

"_id" : ObjectId("5853ea01f7720722b4ded855"),  

"title" : "a blog post",  

"content" : "..."  
}
  

> db.blog.post.update(  
... {
"title":"a blog post"},  
... {
"$push":{"comments":{"name":"joe","email":"joe@qq.com","content":"nice post"}}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.blog.post.findOne()  
{
  

"_id" : ObjectId("5853ea01f7720722b4ded855"),  

"title" : "a blog post",  

"content" : "...",  

"comments" : [  
{
  

"name" : "joe",  

"email" : "joe@qq.com",  

"content" : "nice post"  
}
  
]
  
}
  

>   

  

> db.blog.post.update(  
... {
"title":"a blog post"},  
... {
"$push":{"comments":{"name":"bob","email":"bob@sina.com","content":"good post."}}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.blog.post.findOne()  
{
  

"_id" : ObjectId("5853ea01f7720722b4ded855"),  

"title" : "a blog post",  

"content" : "...",  

"comments" : [  
{
  

"name" : "joe",  

"email" : "joe@qq.com",  

"content" : "nice post"  
},
  
{
  

"name" : "bob",  

"email" : "bob@sina.com",  

"content" : "good post."  
}
  
]
  
}
  

>   


$each
  可以将它应用在一些比较复杂的数组操作中。使用 $each 子操作符,可以通过一次 $push 操作添加多个值。
  比如:下面将三个新元素添加到数组中。如果指定的数组中只包含一个元素,那么等同于和没有使用“$each”的普通的“$push”操作。
  

db.stock.ticket.insert({"_id":"goog"})  
WriteResult({
"nInserted" : 1 })  

>db.stock.ticket.update(  
... ... ... {
"_id":"goog"},  
... ... ... {
"$push":{"hourly":{"$each":}}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.stock.ticket.findOne()  
{
"_id" : "goog", "hourly" : [ 562.776, 562.79, 559.123 ] }  

  要实现上面的操作,下面方法也可以。
  

db.stock.ticket.update(  
... ... ... ... ... {
"_id":"goog"},  
... ... ... ... ... {
"$set":{"hourly":}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.stock.ticket.findOne()  
{
"_id" : "goog", "hourly" : [ 562.776, 562.79, 559.123 ] }  

  而下面这样是不行的
  

db.stock.ticket.update(  
... ... ... ... {
"_id":"goog"},  
... ... ... ... {
"$push":{"hourly":}})  
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  

> db.stock.ticket.findOne()  
{
"_id" : "goog", "hourly" : [ [ 562.776, 562.79, 559.123 ] ] }  
页: [1]
查看完整版本: MongoDB学习笔记三