MongoDB 更新/删除文档(四)

技术小白 2018-01-23 17:31:57 ⋅ 821 阅读


第一部分 更新文档

文档存入数据库之后,就可以采用Update来修改它的内容,

db.collection.update(
#查询条件
   <query>,
#修改器
   <update>,
   {     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。

1.1 创建与删除($set与$unset)

$set 用来指定一个键的值,如果这个键不存在就创建,否则就更新.

> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,
}
> db.users.update({"name":"Mongodb"}, {"$set": {"Other": "Nodejs"}})
> 
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "Other" : "Nodejs"}

添加一个新的字段没有问题, 那么添加一个数组呢?? (当然添加字典也是没问题的,不在此演示)

> db.users.update({"name":"Mongodb"}, {"$set": {"Other": ["Mariadb", "Python"]}})
> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "Other" : [        "Mariadb",        "Python"
    ]
}

删除某个字段---$unset

> db.users.update({"name":"Mongodb"}, {"$unset": {"Other": 1}})

1.2 专职数字($inc)

$inc [increase: 增加] 修改器用来增加已有的键的值,不存在则创建; 只能来增加或减少数字值, 数值可以设置为正负来增加或减少, 仅此用于整数/长整数/双进度浮点数

> db.users.update({"name": "Mongodb"}, {"$inc": {"time": 100}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find()
{ "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 115 }

1.3 数组修改器($push)

如果在之前的数据中添加一个新的科目, 并且存储一个数组中就可以采用**$push**, 之前的$set直接覆盖,那么$push是否会存在这种情况?

> db.users.update({"name": "Mongodb"}, {"$push": {"courses": {"name": "Nodejs", "credit": 10}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.update({"name": "Mongodb"}, {"$push": {"courses": {"name": "Mariadb", "credit": 8}}})

结果

> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "courses" : [
        {            "name" : "Nodejs",            "credit" : 10
        },
        {            "name" : "MariaDB",            "credit" : 8
        }
    ]
}

以上的做法实现了, 向数组中添加元素(不是替换), 但是问题是加入我不希望重复添加相同的数据$push 就不能胜任了接下来实现我们需求的就是 $addToSet

1.4 $addToSet 添加

不重复的将元素添加到集合中--$addTOSet

> db.users.update({"name": "Mongodb"}, {"$addToSet": {"courses": {"name": "Nodejs", "credit": 10}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "courses" : [
        {            "name" : "Nodejs",            "credit" : 10
        },
        {            "name" : "Nodejs",            "credit" : 10
        }
    ]
}

$push 与 $addToSet的异同点:

同:
1. 同样可以向集合中添加数据, 字典数组;

不同:
1. $push可以插入同样的数据,结果同时存在
2. $addToSet会覆盖同样的数据

我们在添加一个属性----评价(evaluate)这个数组, 并将一个数组遍历的存入数据库

我们就可以采用$each与$addToSet结合使用

> db.users.update({"name": "Mongodb"},
 {"$addToSet": {"evaluate": {"$each": ["good", "great", "nice"]}}})

结果如下

> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "courses" : [
        ...
    ],    "evaluate" : [        "good",        "great",        "nice"
    ]
}

1.5 操作数组(删除$pop/$pull)

数组是无序的,如何删除特定的元素----第一个? 最后一个? 匹配的某一些?
如何达到所需要求,Mongodb给出了相应的关键字---$pop $pull

原先添加一些测试数据

> db.users.update({"name": "Mongodb"}, {"$push": {"evaluate": {"$each": ["good1", "good2", "nice1", "nice2"]}}})
> 
....    "evaluate" : [        "good",        "great",        "good1",        "good2",        "nice1",        "nice2"
    ]
1.5.1 $pop 删除首尾数据
#最后一个> db.users.update({"name": "Mongodb"}, {"$pop": {"evaluate": 1}})#第一个> db.users.update({"name": "Mongodb"}, {"$pop": {"evaluate": -1}})

脑洞大开的话, 可以试试别的数字 -_-

1.5.2 $pull 删除匹配数据
> db.users.update({"name": "Mongodb"}, {"$pull": {"evaluate": "great"}})

在此会删除匹配的数据, 参数项不可为数组

1.5.2 操作指定位置的数组元素---$

源数据如下, 需求: 更改课程(courses)中,Nodejs的学分(credit)为99

> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "courses" : [
        {            "name" : "Nodejs",            "credit" : 10
        },
        {            "name" : "Mariadb",            "credit" : 10
        }
    ],
    ...
}

提示: 数组下标是从0开始,并且数组名与对象key都有了

第一种: 依据数据下标, 结合$set, 拆找到指定元素就更改. 缺点: 前提是需要知道位置;
第二种使用MongoDB的关键字--$进行匹配, 注意:只可以更改第一个匹配的数据.

实例如下:

> db.users.update({"name": "Mongodb"}, {"$set": {"courses.0.credit": 100}} )
> db.users.update({"name": "Mongodb"}, {"$set": {"courses.$.credit": 100}} )

WriteResult({    "nMatched" : 0,    "nUpserted" : 0,    "nModified" : 0,    "writeError" : {        "code" : 16837,        "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: courses.$.credit"
    }
})

比着葫芦画瓢但是报错了!!!!
主要原因是update的查询条件返回的不是数组, 所以无法匹配更改

正确的做法为

#在此你会发现,查找项多了两个参数> db.users.update({"name" : "Mongodb","courses.name": "Nodejs"}, {"$set": {"courses.$.credit": 22}})

> db.users.find().pretty()
{    "_id" : ObjectId("58bfb2c61b0dbd8a36332275"),    "name" : "Mongodb",    "time" : 15,    "courses" : [
        {            "name" : "Nodejs",            "credit" : 22
        },
        {            "name" : "MariaDB",            "credit" : 10
        }
    ],
    ....
}
1.5.3 $pushAll添加所有项目
{ $pushAll: { <field>: [ <value1>, <value2>, ... ] } }
{ $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }
> db.users.update({}, {"$pushAll": {"test": [1, 2, 3, 4, 2, 1, 3]}})
> db.users.find().pretty()
{    "_id" : ObjectId("58ca3706250b163ff8331604"),
    .......    "test" : [1,2,3,4,2,1,3]
}
1.5.4 $pullAll删除所有匹配项
{ $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }
> db.users.update({}, {"$pullAll": {"test": [1, 2]}})
> db.users.find().pretty()
{    "_id" : ObjectId("58ca3706250b163ff8331604"),    "name" : "Mongodb",
    ......  "test" : [
        3,
        4,
        3
    ]
}
1.5.5 $each与$addToSet/$push结合使用
    { $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } }
    
    { $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }
1.5.6 $slice

稍后更新

1.5.7 $sort

稍后更新

1.6 第三个参数---upsert

upsert : 如果不存在update的记录,true为插入,默认是false,不插入。(update+insert)

#在执行之前,只有一条数据,不存在{"name": "Nodejs"}> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}})#因为没有设置upsert, 没有匹配上,所以都是0WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })#设置upsert为TRUE, 即成功> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}}, true)
WriteResult({    "nMatched" : 0,    "nUpserted" : 1,    "nModified" : 0,    "_id" : ObjectId("58ca96b56d72019e69b70823")
})

如果再次执行下边的代码, 会在time基础之上+10

> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}}, true)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
1.7 第四个参数---multi

之前的操作都是基于一个的操作,只匹配第一个,但是假如需要匹配多项, 那么就需要设置multi 参数为 true。

更新第一个credit, 如果存在在基础上加1, 否则创建该字段

> db.users.update({"name": "Mongodb"}, {"$inc": {"courses.0.credit": 1}}, true)
> db.users.update({"courses.name": "Nodejs"}, {"$inc": {"courses.$.credit": 10}}, true)
> 

添加一个新的数据

db.users.insert({"name": "Mongodb"})

现在有两条数据, name都为Mongodb, 为每个name=Mongodb的数据添加一个字段为: "teacher: hhw".

> db.users.update({"name": "Mongodb"}, {"$set": {"teacher": "hhw"}}, false, true)

> db.users.find().pretty()
{    "_id" : ObjectId("58c0f8141b0dbd8a364264b8"),    "name" : "Mongodb",    "teacher" : "hhw"}
{    "_id" : ObjectId("58c0f8421b0dbd8a364264b9"),    "name" : "Mongodb",    "time" : 10,    "courses" : [
       ...
    ],    "evaluate" : [
        ...
    ],    "teacher" : "hhw"}

第二部分 删除文档

2.1 remove

只会删除集合users的文档,但是不会删除集合本身,原有的索引也会存在, 但是数据删除时永久性的, 不能撤销.

> db.users.remove();

2.2 deleteOne/deleteMany

db.collection.deleteOne()db.collection.deleteMany()

删除速度更快的可以采用drop_collections("users"), 速度很快但是,集合与索引都删除了.

更多精彩内容请关注“IT实战联盟”公众号哦~~~



全部评论: 0

    我有话说:

    MongoDB 更新/删除文档()

    第一部分 更新文档 文档存入数据库之后,就可以采用Update来修改它的内容, db.collection.update( #查询条件   <query>, #修改器

    MongoDB系列---数据类型/插入文档(三)

    第一部分 BJSON 与 JSON MongoDB文档与JavaScript中的对象很相似,JavaScript中的数据交互格式是JSON格式. JSON的数据格式: 1. null;2. 布尔

    MongoDB系列之----概述(一)

    MongoDB是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。

    MongoDB 数据库的基本操作(二)

    MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

    MongoDB 查询文档(五)

    第一部分 前期准备1.1 插入测试数据db.test1.insertMany

    MongoDB更新(五)

    如果数据库中尚未有数据, 准备测试数据db.test1.insertMany([    {"name": "zhangsan", "age": 19, "score": [90, 80]},    {"na...

    MongoHelper 0.2.5 发布,Spring-Data-MongoDB 增强工具包

    工具包简化 CRUD 操作,并且提供了类 jpa 的数据库操作。

    MongoDB实战篇:数据库备份与恢复/导出与导入

    mongodump命令可以通过参数指定导出的数据量级转存的服务器......

    MongoDB实战篇:高级查询----$elemMatch与aggregate

    基本的Find查询将在其他章节示例,本文主要针对于遇到的问题与解决的方法做个记录,希望可以减少遇到这类问题的

    Mongoose 5.12.5 发布,MongoDB 异步对象模型工具

    Mongoose 是设计用于异步环境的 MongoDB 对象模型工具。Mongoose 支持 promises 和 callbacks。Mongoose 5.12.5 正式发布,本次更新内容如下

    MongoDB 4.4.5 发布

    MongoDB 是一种面向文档的数据库管理系统,用 C++ 等语言撰写而成,以解决应用程序开发社区中的大量现实问题。MongoDBMongoDB Inc. 于 2007 年 10 月开发

    Syncthing 1.11.0 和 1.11.1 发布,连续文件同步工具

    Syncthing 是一个免费开源的工具,它能在你的各个网络计算机间同步文件/文件夹,它的同步数据是直接从一个系统中直接传输到另一个系统的,并且它是安全且私密的。 Syncthing 1

    「开源资讯」Atom 1.52.0 和1.53.0-beta0发布,跨平台文本编辑器

    Atom 同时发布了 1.52.0 和 1.53.0-beta0 版本。Atom 是 GitHub 专门为程序员推出的一个跨平台文本编辑器。具有简洁和直观的图形用户界面,并有很多有趣的特点:支持

    Redis系列 GEO附近的人

    分成4个部分。 我们先将平面切割成个正方形,然...

    极速后台框架 FastAdmin v1.2.0.20210125 新增插件 API 文档生成

    FastAdmin 更新日志 v1.2.0.20210125_beta 新增自定义插件API文档生成 新增登录和鉴权状态显示 新增自定义测试提交参数 优化安装脚本 优化cookie加密 修复系统

    Deepin 深度系统更新(2020.11.25)发布

    深度系统官方发布了深度系统更新(2020.11.25),本次更新部分深度应用,全面优化使用体验,包括磁盘管理器、文件管理器、深度音乐、深度影院、深度相机等。修复部分模块漏洞,提升系统安全性。其他主要

    开源文档系统 MrDoc 0.6.2 版本发布

    MrDoc(觅道文档)是一个基于 Python 开发的在线文档系统,其以 Markdown 语法进行文档编写,集成了两大主流 Markdown 编辑器(Editor.MD 和 Vditor),适合