MongoDB学习笔记四—增删改文档下
$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学习笔记四—增删改文档下的更多相关文章
- MongoDB学习笔记三—增删改文档上
插入insert 单条插入 > db.foo.insert({"bar":"baz"}) WriteResult({ }) 批量插入 > db.fo ...
- MongoDB学习笔记,基础+增删改查+索引+聚合...
一 基础了解 对应关系 -> https://docs.mongodb.com/manual/reference/sql-comparison/ database -> database ...
- MongoDB学习笔记—03 增删改查操作
MongoDB的CURD操作分别通过函数insert().update().find().remove()进行 MongoDB文档新增与删除 MongoDB中关于文档的新增与删除比较简单.主要通过in ...
- SpringBoot学习笔记:Swagger实现文档管理
SpringBoot学习笔记:Swagger实现文档管理 Swagger Swagger是一个规范且完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务.Swagger的目标是对RE ...
- MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系
MongoDB的集合(collection)可以看做关系型数据库的表,文档对象(document)可以看做关系型数据库的一条记录.但两者并不完全对等.表的结构是固定的,MongoDB集合并没有这个约束 ...
- MongoDB学习-->命令行增删改查&JAVA驱动操作Mongodb
MongoDB 是一个基于分布式文件存储的数据库. 由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关 ...
- Mongodb学习笔记四(Mongodb聚合函数)
第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...
- 3、MyBatis.Net学习笔记之增删改
增删改之前先说一下笔记1里提到的一个无法创建ISqlMapper对象的问题. <resultMaps> <resultMap id="FullResultMap" ...
- 【.NET-EF】Entity Framework学习笔记2 - 增删改(没查询)
学习描述:用EF就像是省略了做实体类和DAL类,感觉是很方便,废话不多说,直接写步骤: 1.创建EF的edmx文件 这个其实在笔记1已说过,不过有些细节也要说,所以再说一遍,这里使用的是EF 6.1版 ...
随机推荐
- 闲来无聊,研究一下Web服务器 的源程序
web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...
- [虾扯蛋] android界面框架-Window
从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- java中servlet的各种路径
1. web.xml中<url-pattern>路径,(叫它Servlet路径!) > 要么以“*”开关,要么为“/”开头 2. 转发和包含路径 > *****以“/”开头:相 ...
- TODO:Laravel 内置简单登录
TODO:Laravel 内置简单登录 1. 激活Laravel的Auth系统Laravel 利用 PHP 的新特性 trait 内置了非常完善好用的简单用户登录注册功能,适合一些不需要复杂用户权限管 ...
- java Web项目创建之一(普通java web项目的创建与发布)
1.创建新的web项目 file->new_>Dynamic Web Project(如图) 或file->new->Project->Web->Dynamic W ...
- netty5 HTTP协议栈浅析与实践
一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
- Hawk 4.7 单步调试
单步调试的意义 已经编写的工作流,可能会因为某些外界环境的变化而出错,此时需要排除错误,我们可以使用单步调试. 单步调试的本质,相当于只使用前n个模块,这样就能看到每个步骤下,流的改变. 例子 还是上 ...
- gitHub使用入门和github for windows的安装教程
在看这篇教程之前我想大家也在搜索怎样使用gitHub托管自己的项目,在使用gitHub之前我也遇到过各种问题,在网上我也搜索了很多,但总觉得网上搜索到的东西很多很杂,有的根本不知道是在表达什么.在这过 ...
- Web安全相关(五):SQL注入(SQL Injection)
简介 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据 ...