$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. 加深一下BlockingQueue的认识

    认识BlockingQueue BlockingQueue是一种可以阻塞线程的队列,java中对这种队列提供了方法抽象,BlockingQueue则是抽象的接口. add:添加元素到队列里,添加成功返 ...

  2. Python高手之路【四】python函数装饰器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  3. 用原生js做单页应用

    最近在公司接到一个需求,里面有一个三级跳转.类似于选择地址的时候,选择的顺序是:省份->市->区.如果分三个页面跳转,那么体验非常不好,如果引入其他框架做成单页应用,又比较麻烦.所以可以用 ...

  4. AI人工智能系列随笔

    初探 AI人工智能系列随笔:syntaxnet 初探(1)

  5. 【腾讯Bugly干货分享】Android Linker 与 SO 加壳技术

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57e3a3bc42eb88da6d4be143 作者:王赛 1. 前言 Andr ...

  6. JAVA 分页工具类及其使用

    Pager.java package pers.kangxu.datautils.common; import java.io.Serializable; import java.util.List; ...

  7. Android开发学习——动画

    帧动画> 一张张图片不断的切换,形成动画效果* 在drawable目录下定义xml文件,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长              ...

  8. IT雇员及外包商选择:人品第一

    最近,苹果iOS操作系统和智能手机爆出了一个奇葩故障,在播放特定一段五秒钟的视频时能导致手机死机.唯一的解决办法是按住电源键和Home按键进行手机的重启. 第十八届中国国际高新技术成果交易会在深圳举办 ...

  9. linux系统oracle-ora12505问题解决方案一

    说明:(1)Linux版本 Linux version 2.6.32.12-0.7-default (geeko@buildhost) (gcc version 4.3.4 [gcc-4_3-bran ...

  10. Bluemix中国版体验(二)

    从上一篇到现在大概有一个多月了.时隔一个月再登录中国版Bluemix,发现界面竟然更新了,现在的风格和国际版已经基本保持一致!这次我们来体验一下Mobile Service.不过mobile serv ...