MongoDB学习笔记四—增删改文档下

时间:2023-01-08 10:13:00

$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&period;Net学习笔记之增删改

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

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

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

随机推荐

  1. nodejs安装及环境配置(windows系统)

    作为服务端运行javascript的平台的NodeJs,把前台javascript移到了服务器端,Google V8引擎使其运行效率非常高,它可以异步,无任何阻塞运行程序.nodejs包含http服务 ...

  2. Theano学习笔记:Theano的艰辛安装体验

    http://www.cnblogs.com/hanahimi/p/4127026.html

  3. Spring Boot快速入门

    安装 安装依赖 maven是一个依赖管理工具,我们利用maven进行构建.创建一个maven项目,在pom.xml里面添加依赖项 <?xml version="1.0" en ...

  4. 数据结构随笔-php实现栈

    栈(Stack)满足后进先出(LIFO)的原则: 下面利用php实现栈的相关操作: 本实例栈的基本操作: 入栈(push):向栈内压入一个元素,栈顶指针指向栈顶元素 出栈(pop): 从栈顶去除元素, ...

  5. HTML 使用jQuery选中复选框 简易版

    <html><head>   <meta charset="utf-8">   <script src="jquery-1.7. ...

  6. FbinstTools制作多系统启动U盘(Windows&plus;Linux)

    U盘启动盘制作工具在国内有倆工具,老毛桃.大白菜.也不知道是谁模仿谁的,反正PE肯定是Microsoft的. PE其实就是精简版的Windows维护系统,那如何制作Linux启动盘呢,百度搜“linu ...

  7. QEMU KVM libvirt 手册&lpar;3&rpar; - Storage Media

    访问Hard Drive 使用-hda –hdb qemu-system-x86_64 -enable-kvm -name ubuntutest  -m 2048 -hda ubuntutest.im ...

  8. ThinkPHP&plus;JQuery实现文件的异步上传

    前端代码 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  9. hdu 1151 Air Raid 最小路径覆盖

    题意:一个城镇有n个路口,m条路.每条路单向,且路无环.现在派遣伞兵去巡逻所有路口,伞兵只能沿着路走,且每个伞兵经过的路口不重合.求最少派遣的伞兵数量. 建图之后的就转化成邮箱无环图的最小路径覆盖问题 ...

  10. 每天一个linux命令&lpar;3&rpar;:du命令

    Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是查看当前指定文件或目录(会递归显示子目录)占用磁盘空间大小,还是和df命令有一些区别的. 1.命令格式: du [选 ...