MongoDB 文档字段增删改

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: MongoDB 基于CRUD(create,read,update,delete)方式实现了对集合上的文档进行增删改查。

MongoDB 基于CRUD(create,read,update,delete)方式实现了对集合上的文档进行增删改查。对于集合上字段的增删改,可以使用setunset修改器来实现。也可以使用文档替换的方式来实现。本文主要描述集合上字段的增删改,以及基于选项upsert的更新。

关于MongoDB文档更新可以参考:MongoDB 文档更新

一、语法描述

    db.collection.update(
       <query>,                  //查询或过滤条件
       <update>,                 //修改器(被修改键及内容)
       {                         
         upsert: <boolean>,      //为true或者false,如果为true,未找到匹配文档则创建新文档
         multi: <boolean>,       //用于确定是单行还是更新所有行(true为所有行)
         writeConcern: <document>   //设定写关注,用于确保强一致性还是弱一致性
       }                            //后面的3.2之后的语法参数基本相同
    )

    其他的如updateOne,updateMany等用法请参考:MongoDB 文档更新

    MongoDB集合上所有的写操作特性
            原子性操作(单个文档级别原子性操作)
            _id 字段无法修改,即无法使用一个新的_id值来代替
            由于更新导致文档尺寸超出预期分配的情形,会自动调整填充因子,重新分配空间
            保留文档字段的顺序,但是更新或重命名可能导致字段顺序重新排序(_id总是文档第一个字段)

二、update的几个常用修改器

1、文档更新($set修改器常规更新)

//$set修改器最常用,等同于RDBMS update的set子句
//演示重用的的示例集合数据请参考:mongoDB 比较运算符

> db.persons.find().limit(1).pretty()
{
        "_id" : ObjectId("5864d8d435ac4f57fb2528f8"),
        "name" : "robinson.cheng",
        "age" : 25,
        "email" : "robinson.cheng@qq.com",
        "score" : {
                "c" : 89,
                "m" : 96,
                "e" : 87
        },
        "country" : "USA",
        "books" : [
                "JS",
                "C++",
                "EXTJS",
                "MONGODB"
        ],
        "blog" : "http://blog.csdn.net/leshami"
}
> 
> //使用$set修改器修改age字段
> db.persons.update({name:"robinson.cheng"},{$set:{age:24}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //使用$set修改器修改嵌套文档,使用成员.方式来实现

> db.persons.update({name:"robinson.cheng"},{$set:{"score.c":92}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //查看修改后的结果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,score:1}).pretty()
{
        "name" : "robinson.cheng",
        "age" : 24,
        "score" : {
                "c" : 92,
                "m" : 96,
                "e" : 87
        }
}

2、将文档普通字段转换为数组($set)

//如下,将country设定为数组
> db.persons.update({name:"robinson.cheng"},{$set:{country:["USA","CN","HK"]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,country:1})
{ "name" : "robinson.cheng", "country" : [ "USA", "CN", "HK" ] }

3、文档新增字段($set实现)

//下面使用$set文档新增一个add字段,也可以使用$inc实现新增字段(见后面的描述)
> db.persons.update({name:"robinson.cheng"},{$set:{add:"ShenZhen"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //查看新增字段add
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,add:1})
{ "name" : "robinson.cheng", "age" : 24, "add" : "ShenZhen" }

4、文档删除字段

//注,字段的删除方法为{"$unset":{field_name:1}}

> db.persons.update({name:"robinson.cheng"},{"$unset":{add:1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//验证删除后的结果add未显示
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,add:1})
{ "name" : "robinson.cheng", "age" : 24 }

5、字段值的增加或减少

//当使用$inc修改器时,当字段不存在时,会自动创建该字段,如果存在,则在原有值的基础上进行增加或者减少
//$inc主要是用于专门进行数字的增加或减少,因此$inc只能用于整型,长整形,或者双精度浮点型的值
//$inc不支持字符串,数组以及其他非数字的值
//注,对于$inc的操作,$set也可以完成。$inc存在的理由是$inc更高效

//下面通过$inc新增salary字段
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:1000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 1000 }

//再次执行$inc
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:2000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//查询结果为在原有1000的基础上增加2000,即为3000
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 3000 }

//基于$inc的负值
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:-1500}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//负值后的结果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 1500 }

//下面使用非数字来实现$inc,报错如下
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:"1.5k"}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 14,
                "errmsg" : "Cannot increment with non-numeric argument: {salary: \"1.5k\"}"
        }
})

6、时间戳字段的增加及自动更新($currentDate)

//有时候需要为文档增加最后的更新时间自动,可以使用$currentDate方式来实现
//下面为文档增加lastModified时间戳字段
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:1000},$currentDate: {lastModified:true}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//查看结果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1,lastModified:1})
{ "name" : "robinson.cheng", "salary" : 2500, "lastModified" : ISODate("2017-02-08T08:23:38.361Z") }

//再次更新
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:500},$currentDate: {lastModified:true}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//再次查看结果,时间戳自动被自动更新为最新的时间
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1,lastModified:1})
{ "name" : "robinson.cheng", "salary" : 3000, "lastModified" : ISODate("2017-02-08T08:25:26.865Z") }

7、文档字段重命名($rename)

//下面使用$rename对文档字段重命名
> db.persons.update({name:"robinson.cheng"},{$rename:{"name":"ename"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({ename:"robinson.cheng"},{"_id":0,ename:1})
{ "ename" : "robinson.cheng" }

//对子文档字段进行重命名
> db.persons.update({ename:"robinson.cheng"},{$rename:{"score.c":"score.chinese"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({ename:"robinson.cheng"},{"_id":0,ename:1,score:1})
{ "score" : { "m" : 96, "e" : 87, "chinese" : 92 }, "ename" : "robinson.cheng" }

//对整个集合上所有文档字段进行重命名
> db.persons.count()
12

> db.persons.update({},{$rename:{"name":"ename"}},{multi:true})
WriteResult({ "nMatched" : 12, "nUpserted" : 0, "nModified" : 11 }) //此次修改为11条,因为前面以及修改过1

三、upsert选项用法

// upsert相当于oracle的merge into或者mysql中的replace into
// upsert即是当集合中匹配到满足条件的文档时,则更新文档,否则则是新增文档。前提是该选项的值为true,缺省为flase。

> //下面的演示的是匹配到文档时的例子
> db.persons.update({name:"robinson.cheng"},{$set:{salary:4000}},{upsert:true})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  //此时提示有一个匹配,有一个被更新
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1})
{ "name" : "robinson.cheng", "salary" : 4000 }

> //下面通过upsert方式来新增文档
> db.persons.find({name:"thomas"})  //查找thomas
> db.persons.update({name:"thomas"},{$set:{salary:4000,country:"USA",age:25}},{upsert:true})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1, //此处结果表面有一个upserted,即没有对应得文档,更新的内容作为一个新文档插入到集合
        "nModified" : 0,
        "_id" : ObjectId("589ae6f4e3a46ff8c567f1bf")
})
> db.persons.find({name:"thomas"})
{ "_id" : ObjectId("589ae6f4e3a46ff8c567f1bf"), "name" : "thomas", "salary" : 4000, "country" : "USA", "age" : 25 }

四、小结

a、对于文档上数据的修改有多种方式(修改器),常用的为$set修改器以及$inc
b、$inc是一种高效的数据修改器,通常用于实现数值的增加或减少,仅支持数据类型。
c、对于文档字段的增加,可以使用$set,$unset,$inc,$currentDate等方式
d、对于文档字段的删除,使用$unset方式来实现
e、upsert选项可以实现匹配的文档则更新,不匹配时则插入

DBA牛鹏社(SQL/NOSQL/LINUX)

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
4小时前
|
存储 NoSQL 数据管理
【MongoDB 专栏】MongoDB 文档模型详解
【5月更文挑战第10天】MongoDB 是一种流行的 NoSQL 数据库,以其灵活的文档数据模型著称。文章介绍了文档的基本概念、结构及操作,包括插入、查询、更新和删除。文档特点是灵活且可扩展,适合存储不同结构的数据。优势在于简化数据建模、提升开发效率并适应动态数据。应用场景包括用户信息、日志记录和电商数据管理。但需注意数据一致性和文档大小对性能的影响。理解文档模型有助于高效利用 MongoDB。
【MongoDB 专栏】MongoDB 文档模型详解
|
4小时前
|
存储 NoSQL MongoDB
MongoDB数据模型与文档结构详解
【4月更文挑战第30天】MongoDB是一个基于文档的NoSQL数据库,其数据模型由文档(类似键值对集合,支持嵌套和数组)、集合(无需预定义结构的文档组)和数据库(包含集合的组织单元)构成。文档使用BSON格式,支持多种数据类型。在设计数据模型时,应注意避免过度嵌套,利用索引优化查询,并考虑数据生命周期。MongoDB通过引用处理文档间关系,提供灵活性以适应复杂数据结构。
|
4小时前
|
存储 JSON DataWorks
DataWorks产品使用合集之DataWorks将 MongoDB 中的数组类型写入到 DataWorks 的单个字段时,表示为字符串格式而非 JSON 格式如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
26 3
|
4小时前
|
存储 JSON NoSQL
MongoDB的文档存储格式BSON和JSON的区别
MongoDB的文档存储格式BSON和JSON的区别
|
4小时前
|
NoSQL Go MongoDB
mongodb查询文档内部属性以及数组
mongodb查询文档内部属性以及数组
46 0
|
4小时前
|
NoSQL Java MongoDB
mongoDB动态配置文档名称
mongoDB动态配置文档名称
38 0
|
4小时前
|
SQL NoSQL Java
文档型数据库MongoDB
文档型数据库MongoDB
|
4小时前
|
存储 JSON NoSQL
【MongoDB】<文档型数据库>Windows&Liunx安装MongoDB(无错完整)
【1月更文挑战第26天】【MongoDB】<文档型数据库>Windows&Liunx安装MongoDB(无错完整)
|
4小时前
|
消息中间件 SQL NoSQL
Flink mongodb支持CDAS 到那些下游?如果是不定格式的如何处理呀?mongodb的动态字段。
Flink mongodb支持CDAS 到那些下游?如果是不定格式的如何处理呀?mongodb的动态字段。【1月更文挑战第19天】【1月更文挑战第94篇】
101 6