$slice

如果希望数组的最大长度是固定的,那么可以将 $slice 和 $push 组合在一起使用,就可以保证数组不会超出设定好的最大长度。$slice 的值必须是负整数。

假设$slice的值为10,如果$push 后的数组的元素个数小于10,那么所有元素都会保留。反之,只有最后那10个元素会保留。因此,$slice 可以用来在文档中创建一个队列。

db.class.insert({"班级":"1班"})

WriteResult({ "nInserted" :  })
> db.class.update(
... {"班级":"1班"},
... {"$push":{"students":{
... "$each":["zs","ls","ww"],
... "$slice":-}}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.class.findOne()
{
"_id" : ObjectId("5854b5a0e7d717fcb974637b"),
"班级" : "1班",
"students" : [
"zs",
"ls",
"ww"
]
} > db.class.update(
... {"班级":"1班"},
... {"$push":{"students":{
... "$each":["yyb","rhr","www","qqq","eee","rrr"],
... "$slice":-}}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.class.findOne()
{
"_id" : ObjectId("5854b5a0e7d717fcb974637b"),
"班级" : "1班",
"students" : [
"rhr",
"www",
"qqq",
"eee",
"rrr"
]
}
>

也可以在清理元素之前使用$sort,只要向数组中添加子对象就需清理,先排序后保留指定的个数。

> db.class.update({},{ "班级" : "一班"})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.class.update(
... {"班级":"一班"},
... {"$push":{"students":
... {"$each":[{"name":"aaa","age":},{"name":"bbb","age":},{"name":"ccc","age":}],
... "$slice":-,
... "$sort":{"age":-}}}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.class.findOne()
{
"_id" : ObjectId("5854b5a0e7d717fcb974637b"),
"班级" : "一班",
"students" : [
{
"name" : "bbb",
"age" :
},
{
"name" : "aaa",
"age" :
}
]
}
>

$ne与$addToSet

如果想将数组作为数据集使用,保证数组内的元素不会重复。可以在查询文档中用$ne或者$addToSet来实现。有些情况$ne根本行不通,有些时候更适合用$addToSet。

> db.papers.insert({"authors cited":["yyb"]})
WriteResult({ "nInserted" : })
> db.papers.update({"authors cited":{"$ne":"Richie"}}, {"$push":{"authors cited":"Richie"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.papers.findOne()
{
"_id" : ObjectId("5854c900e7d717fcb974637e"),
"authors cited" : [
"yyb",
"Richie"
]
}
> db.papers.update({"authors cited":{"$ne":"Richie"}}, {"$push":{"authors cited":"Richie"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
>
 db.user.findOne()
{
"_id" : ObjectId("5854cb40e7d717fcb974637f"),
"username" : "joe",
"emails" : [
"joe@example.com",
"joe@gmail.com",
"joe@yahoo.com"
]
} > db.user.update(
... ... {"username":"joe"},
... ... {"$addToSet":{"emails":"joe@gmail.com"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.user.update(
... ... ... {"username":"joe"},
... ... ... {"$addToSet":{"emails":"joe@hotmail.com"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.user.findOne()
{
"_id" : ObjectId("5854cb40e7d717fcb974637f"),
"username" : "joe",
"emails" : [
"joe@example.com",
"joe@gmail.com",
"joe@yahoo.com",
"joe@hotmail.com"
]
}
>

将$addToSet和$each组合起来,可以添加多个不同的值。而用$ne和$push组合就不能实现。

$addToSet与$push的区别:前者添加到数组中时会去重,后者不会。

>db.user.insert({ "username" : "joe"})
> db.user.update(
... {"username" : "joe"},
...
... {"$addToSet":
... {"emails" :{"$each": [
... "joe@example.com",
... "joe@gmail.com",
... "joe@yahoo.com",
... "joe@hotmail.com",
... "joe@hotmail.com"]}}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.user.findOne()
{
"_id" : ObjectId("5854ce5ce7d717fcb9746380"),
"username" : "joe",
"emails" : [
"joe@example.com",
"joe@gmail.com",
"joe@yahoo.com",
"joe@hotmail.com"
]
}
>

从数组中删除元素

$pop

可以从数组任何一端删除元素。

{“$pop”:{“key”:1}}从数组末尾删除一个元素

{“$pop”:{“key”:-1}}从数组头部删除一个元素

> db.class.findOne()
{
"_id" : ObjectId("5854b5a0e7d717fcb974637b"),
"班级" : "一班",
"students" : [
{
"name" : "bbb",
"age" :
},
{
"name" : "aaa",
"age" :
}
]
}
> db.class.update(
... {"班级" : "一班"},
... {"$pop":{"students":}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.class.findOne()
{
"_id" : ObjectId("5854b5a0e7d717fcb974637b"),
"班级" : "一班",
"students" : [
{
"name" : "bbb",
"age" :
}
]
}
>

$pull

有时需要基于特定条件来删除,而不仅仅是依据元素位置,这时可以使用$pull。$pull会将所有匹配的文档删除,而不是只删除一个。

> db.list.insert(
... {"todo":["dishes","laundry","dry cleaning"]})
WriteResult({ "nInserted" : })
> db.list.update({},{"$pull":{"todo":"laundry"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.list.findOne()
{
"_id" : ObjectId("585690afc5b0525a48a441b4"),
"todo" : [
"dishes",
"dry cleaning"
]
}
>

数组操作符只能用于包含数组值的键。例如:不能将一个整数插入数组,也不能将一个字符串从数组中弹出。要修改标量值,使用$set或$inc。

基于位置的数组修改器

有两种方法操作数组中的值:通过位置或者定位操作符($)

位置

通过数组位置来操作。数组都是以0开头的,可以将下标直接作为键来选择元素。

> db.blog.insert(
... {
... "content": "...",
... "comments": [
... {
... "comment": "good post",
... "author": "john",
... "votes":
... },
... {
... "comment": "i thought it was too short",
... "author": "claire",
... "votes":
... },
... {
... "comment": "free watches",
... "author": "alice",
... "votes": -
... }
... ]
... })
WriteResult({ "nInserted" : }) > db.blog.update({"content":"..."},{"$inc":{"comments.0.votes":}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.blog.findOne()
{
"_id" : ObjectId("585694e4c5b0525a48a441b5"),
"content" : "...",
"comments" : [
{
"comment" : "good post",
"author" : "john",
"votes" :
},
{
"comment" : "i thought it was too short",
"author" : "claire",
"votes" :
},
{
"comment" : "free watches",
"author" : "alice",
"votes" : -
}
]
}
>

定位操作符$

如果无法知道要修改的数组的下标,可以使用定位操作符$,用来定位查询文档已经匹配的元素,并进行更新。

> db.blog.update(
... {"comments.author":"john"},
... {"$set":{"comments.$.author":"jim"}})
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.blog.findOne()
{
"_id" : ObjectId("585694e4c5b0525a48a441b5"),
"content" : "...",
"comments" : [
{
"comment" : "good post",
"author" : "jim",
"votes" :
},
{
"comment" : "i thought it was too short",
"author" : "claire",
"votes" :
},
{
"comment" : "free watches",
"author" : "alice",
"votes" : -
}
]
}
>

upsert

upsert是update()的第三个参数。表示没有则创建,有则正常更新。

> db.analytics.update({"url":"/blog"},{"$inc":{"pageviews":}},true)
WriteResult({
"nMatched" : ,
"nUpserted" : ,
"nModified" : ,
"_id" : ObjectId("58569d3cb6687ca8dfad4e01")
})
> db.analytics.findOne()
{
"_id" : ObjectId("58569d3cb6687ca8dfad4e01"),
"url" : "/blog",
"pageviews" :
}
> db.analytics.update({"url":"/blog"},{"$inc":{"pageviews":}},true)
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.analytics.findOne()
{
"_id" : ObjectId("58569d3cb6687ca8dfad4e01"),
"url" : "/blog",
"pageviews" :
}
>

$setOnInsert

在创建文档的同时创建字段并为它赋值,但是在之后的所有更新操作中在,这个字段的值都不在改变。

$setOnInsert只会在文档插入时设置字段的值。

在预置或者初始化计数器时,或者对于不使用ObjectIds的集合来说,“$setOnInsert”是非常有用的。

> db.user.update({},{"$setOnInsert":{"createAt":new Date()}},true)
WriteResult({
"nMatched" : ,
"nUpserted" : ,
"nModified" : ,
"_id" : ObjectId("58569fe1b6687ca8dfad4e02")
})
> db.user.findOne()
{
"_id" : ObjectId("58569fe1b6687ca8dfad4e02"),
"createAt" : ISODate("2016-12-18T14:40:33.273Z")
}
> db.user.update({},{"$setOnInsert":{"createAt":new Date()}},true)
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.user.findOne()
{
"_id" : ObjectId("58569fe1b6687ca8dfad4e02"),
"createAt" : ISODate("2016-12-18T14:40:33.273Z")
}
>

save

一个shell函数,不存在创建,反之则更新文档。

它只有一个参数:文档。要是这个文档含有“_id”键,save会调用upsert。否则会调用insert。在shell中快速对文档进行修改。

> db.user.save({"x":,"y":})
WriteResult({ "nInserted" : })
> var x=db.user.findOne()
> x.num= > db.user.save(x)
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.user.findOne()
{
"_id" : ObjectId("5856a230c5b0525a48a441be"),
"x" : ,
"y" : ,
"num" :
}

更新多个文档

默认情况下,只会更新匹配的第一个文档。要更新多个文档,需要将update的第4个参数设置为true。

想要知道多文档更新到底更新了多少文档,可以运行getLastError命令。键n的值就是被更新文档的数量。

> db.coll.find()
{ "_id" : ObjectId("5856994bc5b0525a48a441b9"), "x" : "a" }
{ "_id" : ObjectId("58569966c5b0525a48a441ba"), "x" : "bbb" }
{ "_id" : ObjectId("5856996fc5b0525a48a441bb"), "x" : "c" }
> db.coll.update({},{"$set":{"x":}},false,true )
WriteResult({ "nMatched" : , "nUpserted" : , "nModified" : })
> db.runCommand({getLastError:})
{
"connectionId" : ,
"updatedExisting" : true,
"n" : ,
"syncMillis" : ,
"writtenTo" : null,
"err" : null,
"ok" :
}
>

返回被更新的文档

通过findAndModify命令得到被更新的文档。返回的是修改之前的文档。

对于操作队列以及执行其他需要进行原子性取值和赋值的操作非常方便。

 ps=db.runCommand({"findAndModify":"processes", "query":{"status":"ready"},
"sort":{"pirority":-},
"update":{"$set":{"status":"Running"}}})
{
"lastErrorObject" : {
"updatedExisting" : true,
"n" :
},
"value" : {
"_id" : ObjectId("5857c939d7a32a888bd79c47"),
"pirority" : ,
"status" : "ready"
},
"ok" :
}
> db.processes.findOne("_id":ps.value._id)
--19T19::04.904+ E QUERY [thread1] SyntaxError: missing ) after argument list @(shell):: > db.processes.findOne({"_id":ps.value._id})
{
"_id" : ObjectId("5857c939d7a32a888bd79c47"),
"pirority" : ,
"status" : "Running"
}
>

findAndModify可以使用update键也可以使用remove键。Remove键表示将匹配的文档从集合里面删除。

> ps=db.runCommand({"findAndModify":"processes", "query":{"status":"ready"},
"sort":{"priority":-},
"remove":true}).value
{
"_id" : ObjectId("5857c9b1d7a32a888bd79c48"),
"pirority" : ,
"status" : "ready"
} > db.processes.findOne({"_id":ps._id})
null

MongoDB学习笔记四—增删改文档下的更多相关文章

  1. MongoDB学习笔记三—增删改文档上

    插入insert 单条插入 > db.foo.insert({"bar":"baz"}) WriteResult({ }) 批量插入 > db.fo ...

  2. MongoDB学习笔记,基础+增删改查+索引+聚合...

    一 基础了解 对应关系 -> https://docs.mongodb.com/manual/reference/sql-comparison/ database -> database ...

  3. MongoDB学习笔记—03 增删改查操作

    MongoDB的CURD操作分别通过函数insert().update().find().remove()进行 MongoDB文档新增与删除 MongoDB中关于文档的新增与删除比较简单.主要通过in ...

  4. SpringBoot学习笔记:Swagger实现文档管理

    SpringBoot学习笔记:Swagger实现文档管理 Swagger Swagger是一个规范且完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务.Swagger的目标是对RE ...

  5. MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系

    MongoDB的集合(collection)可以看做关系型数据库的表,文档对象(document)可以看做关系型数据库的一条记录.但两者并不完全对等.表的结构是固定的,MongoDB集合并没有这个约束 ...

  6. MongoDB学习-->命令行增删改查&JAVA驱动操作Mongodb

    MongoDB 是一个基于分布式文件存储的数据库. 由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关 ...

  7. Mongodb学习笔记四(Mongodb聚合函数)

    第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...

  8. 3、MyBatis.Net学习笔记之增删改

    增删改之前先说一下笔记1里提到的一个无法创建ISqlMapper对象的问题. <resultMaps> <resultMap id="FullResultMap" ...

  9. 【.NET-EF】Entity Framework学习笔记2 - 增删改(没查询)

    学习描述:用EF就像是省略了做实体类和DAL类,感觉是很方便,废话不多说,直接写步骤: 1.创建EF的edmx文件 这个其实在笔记1已说过,不过有些细节也要说,所以再说一遍,这里使用的是EF 6.1版 ...

随机推荐

  1. ImageView缩放选项

    ImageView.ScaleType 将图片边界缩放到所在view边界时的缩放选项. Options for scaling the bounds of an image to the bounds ...

  2. tLinux 2.2下安装Mono 4.8

    Tlinux2.2发行版基于CentOS 7.2.1511研发而成,内核版本与Tlinux2.0发行版保持完全一致,更加稳定,并保持对Tlinux2.0的完全兼容.Mono 4版本要求CentOS 7 ...

  3. C语言 · 整数平均值

    编写函数,求包含n个元素的整数数组中元素的平均值.要求在函数内部使用指针操纵数组元素,其中n个整数从键盘输入,输出为其平均值. 样例输入: (输入格式说明:5为输入数据的个数,3 4 0 0 2 是以 ...

  4. .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]

    构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...

  5. 结巴分词3--基于汉字成词能力的HMM模型识别未登录词

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 算法简介 在 结巴分词2--基于前缀词典及动态规划实现分词 博 ...

  6. iOS审核这些坑,腾讯游戏也踩过

    作者:Jamie,专项技术测试工程师,在iOS预审和ASO优化领域从事专项测试相关工作,为腾讯游戏近100个产品提供专项服务. WeTest 导读 在App上架苹果应用商店的过程中,相信大多数iOS开 ...

  7. 自己实现一个javascript事件模块

    nodejs中的事件模块 nodejs中有一个events模块,用来给别的函数对象提供绑定事件.触发事件的能力.这个别的函数的对象,我把它叫做事件宿主对象(非权威叫法),其原理是把宿主函数的原型链指向 ...

  8. MSYS2环境下编译X265

    HEVC(High Efficiency Video Coding),是一种新的视频压缩标准.可以替代H.264/ AVC编码,使得保持相同质量的情况下,体积减少40%左右.目前有多种实现版本,x26 ...

  9. 新手学习web遇到的一些乱码问题

    在新手学习web网站学习的时候经常会遇到?????这种乱码,对于刚起步的菜鸟来说真的很头痛,很容易打击继续学的信心当然了对于菜鸟的我最近也遇到过乱码问题,沉浸其中不能自拔,爱的深啊!!!!!我所遇到的 ...

  10. 推荐10款超级有趣的HTML5小游戏

    HTML5的发展速度比任何人的都想像都要更快.更加强大有效的和专业的解决方案已经被开发......甚至在游戏世界中!这里跟大家分享有10款超级趣味的HTML5游戏,希望大家能够喜欢! Kern Typ ...