zoukankan      html  css  js  c++  java
  • MongoDB文档操作

    一、插入并保存文档

    1.1 insert()方法

    1.2 save()方法

    1.3 批量插入

    1.4 插入原理与方法

    二、删除文档

    2.1 remove()方法

    2.2 deleteOne()以及deleteMany()

    2.3 drop()

    三、文档更新

    3.1 原子性

    3.2 update()方法

    3.3 文档替换

    3.4 修改器

    3.4.1 $set

    3.4.2 $inc

    3.5 数组修改器

    3.6 数组作为数据集

    3.7 删除数组元素

    3.8 基于位置的数组修改器

    3.8.1 通过位置

    3.8.2 定位操作符

    3.9 修改器速度

    3.10 多个文档的更新

    参考文献

    一、插入并保存文档

    1.1 insert()方法

        db.COLLECTION_NAME.insert(document)

        insert()方法是向文档中插入数据最基本的方法,该方法参数接受一个文档,将文档加入到目标集合中。

        如将文档{name:"xxx",age:25}插入集合foo中,只需要如下操作:

            db.foo.insert({name:"xxx",age:25})

        就可在集合中插入该文档。

        需要注意的是,因为我们插入的文档中没有"_id"键,所以这个操作会给文档增加一个自动生成的"_id"键,然后再将其保存在数据库中。这个键并不是地址,也不是简单递增的,而是通过"时间戳+机器编号+进程编号+序列号"生成,所以每个"_id"都是唯一的。如下图所示"_id"为:5bbd4dd38f06ac759d5e8a00,就可分解为时间戳(前四字节):5bbd4dd3 + 机器号(三字节):8f06ac + 进程编号(两字节):759d + 序列号(三字节):5e8a00 。

    1.2 save()方法

        save()是一个shell函数,它不仅仅支持插入操作,还支持更新操作,它只有一个参数:文档,说的更详细些的话,则是该文档的"_id"键的值,如果已有一个文档具有相同的"_id"键值,则执行更新操作,具体则是调用upsert()函数,否则则调用insert()执行更新操作。

    1. db.collection.save(  
    2.    <document>,  
    3.    {  
    4.      writeConcern: <document>  
    5.    }  
    6. )  

    1.3 批量插入

        除了insert()方法外,还可使用batchInsert()方法实现批量插入,该函数与insert()方法不同的地方在于,它接受一个文档数组作为参数。    

    例子:在集合foo中插入{name:"aaa",age:20}, {name:"bbb",age:25}, {name:"ccc",age:30}三条文档:

    1. db.foo.batchInsert([{name:"aaa",age:20}, {name:"bbb",age:25}, {name:"ccc",age:30}])  

    1.4 插入原理与方法

        当执行数据插入的时候,驱动程序会把数据转化成BSON格式,然后将数据导入数据库。数据库会解析BSON,并对其进行最基本的检查:检查文档的基本结构。如文档大小(应小于16MB),"_id"字段等。因此非法数据是无法被甄别的,所以需要对数据源的数据进行判断,或者在数据插入数据库之前做数据校验。

    二、删除文档

    2.1 remove()方法

    1. db.collection.remove(  
    2.    <query>,  
    3.    <justOne>  
    4. )  

      MongoDB v2.6版本对remove()函数进行了更新,修改了参数。

    5. db.collection.remove(  
    6.    <query>,  
    7.    {  
    8.      justOne: <boolean>,  
    9.      writeConcern: <document>  
    10.    }  
    11. )  

      该函数的所有参数都为可选参数,如果全为空,则代表删除集合里的所有文档。

    • query :(可选)删除的文档的条件。
    • justOne : (可选)如果设为 true 1,则只删除一个文档。
    • writeConcern :(可选)抛出异常的级别。

       

    2.2 deleteOne()以及deleteMany()

        deleteOne()以及deleteMany()可以认为是remove()方法的拆解,deleteOne()删除满足条件的一个文档,deleteMany()删除满足条件的所有文档

    1. db.collection.deleteOne(  
    2.    <filter>,  
    3.    {  
    4.       writeConcern: <document>,  
    5.       collation: <document>  
    6.    }  
    7. )  
    8.     
    9. db.collection.deleteMany(  
    10.    <filter>,  
    11.    {  
    12.       writeConcern: <document>,  
    13.       collation: <document>  
    14.    }  
    15. )  

    2.3 drop()

        drop()方法并不对文档进行操作,而是直接删除集合,该函数适用于上文remove()无参数的情况,该函数直接删除集合比删除所有的文档效率更高。

    1. db.collection.drop( { writeConcern: <document> } )  

    三、文档更新

    3.1 原子性

        在MongoDB中,更新单个的文档操作是原子性的。默认情况下,如果一个update()更新多个文档,那么对每个文档的更新是原子性的,但是对整个update而言则不是原子性的。有可能存在前一个文档更新成功,后面的文档更新失败的情况。由于单个文档的更新是原子性的,如果两个更新同时发生,就会出现阻塞,先到的先执行,所以文档最终结果由靠后的操作决定。

    3.2 update()方法

    1. db.collection.update(  
    2.    <query>,  
    3.    <update>,  
    4.    {  
    5.      upsert: <boolean>,  
    6.      multi: <boolean>,  
    7.      writeConcern: <document>,  
    8.      collation: <document>,  
    9.      arrayFilters: [ <filterdocument1>, ... ]  
    10.    }  
    11. )  

    update()方法有两个参数,一个是查询文档,用于定位需要更新的目标文档;另一个是修改器,用于说明要对找到的文档进行哪些修改。

    3.3 文档替换

        替换操作是用一个新的文档替换旧的文档,这一般用于修改比较大的情况。该操作需要一个中间变量来存储新值,最后再将旧值覆盖。

        下图使用该操作完成了文档值的更新操作:将"xi"的信息替换为"xixi",当然,这存在着更好的方法。

        另外,使用update()更新时最好指定一个唯一的键,如"_id",以防匹配到相同的字段导致跟新失败。

    3.4 修改器

    3.4.1 $set

        "$set"可以完成特定字符的修改,如用来指定一个字段的值。如果该字段不存在,则创建它。

        下图对"name":"ahn"文档中的"status"值进行修改,将原来的"A"改为"D"。

        "$set"还可用来修改键的类型以及内嵌文档,使用"$unset"还可将键删除。

    3.4.2 $inc

        "$inc"可以对数据进行增加或减少,这个操作只针对数字类型,如整形、长整形与双精度浮点型。如果操作的该键不存在,则创建一个。

        如将info集合中name: "wangsan"文档对应的age减2:

    3.5 数组修改器

        "$push"将数据插入数组末尾,如果没有该数组,则创建一个。

        如在info集合中数组元素的追加,对name为'bob'的文档添加一个数组元素。

        "each""$push"配合使用,可以一次性push多个值。

    1. db.info.update({ "name" : "bob"},{$push: {"detail": {$each: [{"city" : "Beijing"},{ "city" : "Shanghai"}]}}})  

      上诉操作可在"detail" 中插入两个值。

      "$slice"+"$push"可规定数组长度,"$slice"的值必须为负整数。

      "$sort"则可根据某字段的值对所有对象进行排序。

    3.6 数组作为数据集

        "$addToSet"向数组中添加元素,如果元素已经存在就不添加。

        "$addToSet"+"$set":添加多个不重复的值。

    3.7 删除数组元素

        "$pop"将数组看成队列,每次pop都删除一个元素。{"$pop":{"key":1}}从数组末尾删除一个元素,"key":-1则从头部删除一个元素。

        "$pull"可根据条件来删除元素。如db.foo.update({},{"$pull":{"class":"English"}})可将class数组中的"English"元素删除。

    3.8 基于位置的数组修改器

    3.8.1 通过位置

        数组下标可直接作为键来选择元素,且以0开头。

        如过我们要将上图文档中detail数组里第一个元素的"class"元素改为"0701",则可用下面的方法:

    1. db.info.update({ "name" : "bob"},{$set: {"detail.0.class":"0701"}})  

    3.8.2 定位操作符

        但很多时候,我们并不知道需要修改的数组的下标,所以我们就需要使用定位操作符"$",用来定位查询文档已经匹配的数组元素,并进行更新。

        如上面的修改"class",使用定位符如下所示:

        另外,定位符只更新匹配到的第一个元素。

    3.9 修改器速度

        最初将文档插入到MongoDB时,一次插入的文档在磁盘上的位置是相邻的,且文档之间没有多余的空间。因此当一个文档变大时,原有的位置就无法放下该文档了,所以这个文档就会被移动位置。

        文档创建之初:(该示例源于《MongoDB权威指南》p.43)

        当对中间的文档的数据进行增加时,这个文档就会被移动到文档尾部:

        当MongoDB不得不移动文档时,它会修改集合的填充因子——为每个新文档预留的增长空间。初始化时,填充因子为1,即完全没有多余的空间。在执行完上面的操作后,填充因子扩大为1.5,即每个新加入的文档在之后预留自身1/2大小的空间。如果文档更新操作频繁,移动次数多,填充因子就会增大。反之,不再有文档移动,填充因子就会缓慢减小。

     

        这也是有时push成为系统瓶颈的原因,文档更新造成文档磁盘结构的变化,导致大量的硬盘读写操作。

    3.10 多个文档的更新

        默认的update操作只会更新第一个匹配,要对数据进行批量更新,则需要使用update的第四个参数,将其设为true,表示是否更新全部查到的文档。而有第四个就需要第三个,第三个参数也接收bool类型,表示是否要将我们更新的文档作文新文档插入,默认为false。

        例子:将info集合中将所有status为"B"对应的文档值的status全部改成"B+":

    参考文献:

    《MongoDB权威指南》 人民邮电出版社

    《NoSQL数据库原理与应用》 学校编著

        MongoDB官方文档

  • 相关阅读:
    mysql存储过程的优点
    MySQL复制
    优化数据库的方法
    MySQL表分区
    Http请求
    memcache和redis的区别
    触发器实现原理
    PHP常见数组函数与实例
    git 打包指定提交过的代码
    发送HTTP请求方法
  • 原文地址:https://www.cnblogs.com/magicxyx/p/9774026.html
Copyright © 2011-2022 走看看