• (4)详解MongoDB的创建、更新、删除文档


    1. 插入

    1.1 命令:insert

    1.2 举例:

    > db.blog.insert({"author":"tian","title":"my first mongodb blog"})

    查询结果:

    > db.blog.find()
    { "_id" : ObjectId("500bb4b44daafbf976598437"), "author" : "tian", "title" : "my
    first mongodb blog" }

    1.3 说明:

    1)当我们要插入的集合(这里是blog)不存在时,mongodb会在第一次插入式自动创建一个;

    2)插入的每一条文档,除了我们制定的键(这里有2个键,author和title),还会自动增加一个_id键,相当于关系型数据库的主键,如果我们没有指定的话。

    该键对于一个集合必须是唯一的,它可以使任意类型,默认是ObjectId对象。

    由于mongodb一开始设计就是用来作为分布式数据库的,因此没有采用自增长的方式来创建_id键,因为在不同的服务器上同步自增长主键费时又费力。

    关于ObjectId,更多可以参考:http://www.mongodb.org/display/DOCS/Object+IDs

    当然我们也可以自己指定:

    > db.blog.insert({"_id":2012,"author":"tian","title":"my 2nd mongodb blog"})
    > db.blog.find()
    { "_id" : ObjectId("500bb4b44daafbf976598437"), "author" : "tian", "title" : "my
     first mongodb blog" }
    { "_id" : 2012, "author" : "tian", "title" : "my 2nd mongodb blog" }
    1.4 插入原理:
    当我们将数据插入到mongodb数据库时,数据会被转换成BSON的形式(BSON是mongodb存储数据的形式,类似JSON的,是轻量的二进制格式,
    能将mongodb的所有文档表示为字节字符串,数据库能理解BSON,存在磁盘上的文档也是BSON格式,更多请参考: http://www.bsonspec.org/),
    然后存入数据库。
    在这个阶段,mongodb只检查2件事:
    1)是否包含_id键;
    2)文档是否超过16M,注意,这里的大小是转成BSON格式以后的大小,可以通过Object.bsonsize(your-object)查看大小;(以mongodb 1.8为准)
    只要这两点满足,就会将文档原本的存入到数据库
    这样做有好处也有副作用,副作用就是可以插入无效的数据,好处就是可以使数据库更安全,远离注入式攻击,因为插入不执行代码。
     

    2. 删除
     

    2.1 命令:remove

     

    2.2 举例:

    > db.blog.remove({"title":"my first mongodb blog"})
    > db.blog.remove()
    2.3 说明:
    1) 在上面的2个例子中,第一个例子的remove接受一个参数,用于限定要删除的文档,第二个例子没有指定参数,注意,这种操作是很危险的,因为它将删除整个集合里的文档,但是集合以及索引会被保留,第二个例子等价于db.blog.remove({})
     

    2) 删除是永久性的,不能撤销,也不能恢复

     

    3) 删除文档的速度相当快,如果要删除整个集合里的文档,可以采用db.drop_collection(your-collection),然后重建集合和索引,该方法速度非常快,唯一的缺点是整个集合都被删除了,包括索引

     

    4) 根据_id键来删除文档的效率是最高的

     

    5) 考虑一种比较极端,或者高并发可能发生的情况,当你要删除一个集合里的文档时,刚好有另一个进程在update其中的文档,在这种情况下,正被update的文档是不会被删除的,如果这并不是你想要的,可以通过制定参数$atomic参数为true来删除所有满足条件的文档,如:db.blog.remove({"author":"tian",$atomic:true}),当然,这样做也是有副作用的,就是当我们执行remove操作的时候,将阻止其他操作。

     

    3. 更新

     

    3.1 命令:update

     

    3.2 举例:

     
    > var mypost = db.blog.findOne({"_id":ObjectId("500bc4304daafbf976598439")})
    > mypost.author="tian.chen"
    tian.chen
    > mypost
    {
            "_id" : ObjectId("500bc4304daafbf976598439"),
            "author" : "tian.chen",
            "title" : "my first mongodb blog"
    }
    > db.blog.update({"_id":ObjectId("500bc4304daafbf976598439")},mypost)
    > db.blog.findOne({"_id":ObjectId("500bc4304daafbf976598439")})
    {
            "_id" : ObjectId("500bc4304daafbf976598439"),
            "author" : "tian.chen",
            "title" : "my first mongodb blog"
    }
    3.3 说明:
    1) 我们首先通过findOne来获取一个文档,并赋值给mypost,然后,修改mypost的author键,最后再通过db.blog.update更新文档
    2)  更新时匹配多个文档,更新的时候,由于第二个参数的存在就会产生重复的_id键,就会报错。怎么说呢,举个例子
    > db.blog.find()
    { "_id" : ObjectId("500bc4304daafbf976598439"), "author" : "tian.chen", "title"
    : "my first mongodb blog", "age" : 28 }
    { "_id" : 2012, "author" : "tian.chen", "title" : "my 2nd mongodb blog", "age" :
     6 }
    > var tianpost=db.blog.findOne({"author":"tian.chen","age":6})
    > tianpost
    {
            "_id" : 2012,
            "author" : "tian.chen",
            "title" : "my 2nd mongodb blog",
            "age" : 6
    }
    > tianpost.age=26
    26
    > db.blog.update({"author":"tian.chen"},tianpost)
    cannot change _id of a document old:{ _id: ObjectId('500bc4304daafbf976598439'),
     author: "tian.chen", title: "my first mongodb blog", age: 28.0 } new:{ _id: 201
    2.0, author: "tian.chen", title: "my 2nd mongodb blog", age: 26.0 }

    在这个例子中,我们的post集合里包含2个文档,我们要将第二个文档的age改成26,首先通过author和age获取一个文档并赋值给tianpost,在这里,tianpost也是具有_id键的,其值为2012,然后,我们将tianpost的age改成26后,然后通过author=tian.chen查找文档,将其update为tianpost,问题就出现在这里,通过author=tian.chen查找文档时,首先找到第一个文档,其_id为 ObjectId('500bc4304daafbf976598439'),而tianpost._id=2012,我们知道_id是不能修改的,结果就报错了!

    为了避免这种情况,最好确保更新总是指定唯一文档。

    3.4 使用修改器

    更新修改是种特殊的键,用来指定复杂的操作,如调整,增加或删除键,还可能操作数据或内嵌的文档。

    假设有这样一个文档:

    {

    "_id" : 2012,

    "age" : 26,

    "author" : "tian.chen",

    "pageviews" : 1,

    "title" : "my 2nd mongodb blog"

    }

    其中的键pageviews表示该post被阅读的次数,每阅读一次就增加1,这时,我们可以使用$inc修改器

    > db.blog.update({"_id":2012},{"$inc":{"pageviews":1}})

    3.4.1 $set修改器

    $set修改器用来指定一个键的值,如果这关键不存在就创建它,这对于修改来说是很方便的,因为我们通常修改的只是及个别的键的值的。

    假设我们要修改下面文档的age:

    {

    "_id" : 2012,

    "age" : 26,

    "author" : "tian.chen",

    "pageviews" : 1,

    "title" : "my 2nd mongodb blog"

    }

    如果我们只是简单的用db.blog.update({"_id":2012},{"age":28}),那么,将会用{"age":28}替换掉整个文档,这个时候,$set修改器就很有用处了:

    db.blog.update({"_id":2012},{"$set":{"age":28}})

    当然,也可以修改多个:

    db.blog.update({"_id":2012},{"$set":{"age":28,"author":"tian"}})

    用$set可以修改键的值,如果键不存在就创建它,与之对应的,用$unset可以删除键,如:

    db.blog.update({"_id":2012},{"$unset":{"pageviews":1}})

    这样,就会将文档中的pageviews键删除掉

    3.4.2 $inc修改器

    正如我们在上面看到的,$inc修改器用来增加键的值.

    需要注意的是$inc只能应用于整数、长整数、双精度浮点数,同时$inc的键的值必须为数字,如果要修改其他类型,应使用上面的$set

    3.4.3 数组修改器 $push & $pop

    如果指定的键存在,$push就会向已有的数据末尾加入一个元素,如果没有,则会创建一个新的数组

    如:

    >db.blog.update({"_id":2012},{$push:{"comments":{"name":"jake","content":"nice post"}}})

    查出来的结果为:

    > db.blog.find()
    { "_id" : ObjectId("500bc4304daafbf976598439"), "author" : "tian.chen", "title"
    : "my first mongodb blog", "age" : 28 }
    { "_id" : 2012, "age" : 28, "author" : "tian", "comments" : [ { "name" : "jake",
    "content" : "nice post" } ],
    "title" : "my 2nd mongodb blog" }

    有时候,我们可能会希望,如果一个值在数组中不存在,就添加进去,可以用如下方式来实现,即通过$ne来实现:

    > db.papers.insert({"title":"mongodb post","authors":["tian"]})

    > db.papers.update({"authors":{"$ne":"harry"}},{$push:{"authors":"harry"}})

    { "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "tian", "harry" ],
    "title" : "mongodb post" }

    也可用$addToSet来实现,因为$ne并不总是可行:

    > db.papers.update({"_id": ObjectId("500c0098886e42d4a1a1bff5")},
    ... {"$addToSet":{"authors":"jerry"}})

    >{ "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "tian", "harry", "
    jerry" ], "title" : "mongodb post" }

    $addToSet还有一个妙处,通过与$each结合,可以插入多个值,当然,如果值已经在数组中,就不会被添加进去:

    > db.papers.update({"_id": ObjectId("500c0098886e42d4a1a1bff5")},
    ... {"$addToSet":
    ... {"authors":{"$each":["tian","jerry","mike"]}}})

    { "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "tian", "harry", "
    jerry", "mike" ], "title" : "mongodb post" }

    "tian","jerry"已经存在,因此没有重复添加,"mike"不存在,被添加进来了。

    删除数组的元素可以用$pop或$pull

    $pop主要用于删除数组头部或尾部的值{$pop:{key:-1}}和{$pop:{key:1}}

    > db.papers.find()
    { "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "tian", "harry", "
    jerry", "mike"
    ], "title" : "mongodb post" }
    > db.papers.update({"_id": ObjectId("500c0098886e42d4a1a1bff5")},
    ... {$pop:{"authors":1}}
    ... )
    > db.papers.find()
    { "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "tian", "harry", "
    jerry"
    ], "title" : "mongodb post" }
    > db.papers.update({"_id": ObjectId("500c0098886e42d4a1a1bff5")},
    ... {$pop:{"authors":-1}})
    > db.papers.find()
    { "_id" : ObjectId("500c0098886e42d4a1a1bff5"), "authors" : [ "harry", "jerry" ]
    , "title" : "mongodb post" }

    可以发现{$pop:{key:-1}}删除尾部,而{$pop:{key:1}}删除头部的。

    更经常的,我们希望通过值来判断,这时候就可以用$pull,{"$pull":{key:value}}

    3.5 upsert更新

    upsert是一种特殊的更新,要是没有符合更新条件的文档,就会以这个条件和文档为基础创建一份新的文档。如果有匹配的文档,则正常更新。

    假设我们有一个集合analytics,用来记录每个url的访问次数,每访问一次就给pageviews键加1,正常情况,我们需要判断当前访问的url有没有存在,如果没有,则添加,有则更新。

    采用upsert,我们可以有更优雅的写法:

    db.analytics.update({"url":"/blog"},{"$inc":{"pageviews":1}},true)

    在这里,我们通过给update传递第三个参数表示upsert

    3.6 save函数

    save跟upsert有点类似,也是不存在时插入,存在时更新。不同的是save只有一个参数。看下面的例子:

    > var x = db.blog.findOne({"_id":2012})
    > x.age=99
    99
    > db.blog.save(x)
    > db.blog.find({"_id":2012})
    { "_id" : 2012, "age" : 99, "author" : "tian", "comments" : [   {       "name" :
    "jake",        "content" : "nice post" },      {       "name" : "tina",
    "content" : "not too bad" } ], "title" : "my 2nd mongodb blog" }

    3.7 更新多个文档

    在前面的例子中,我们都是只更新一个文档,mongodb目前也是默认只更新一个文档。我们可以通过对update指定第四个参数,来更新多个文档

    图像 1

    在上面的例子中,我们对比了没传第四个参数和传第四个参数进行更新的区别,传第四个参数后,符合条件的都会更新。

    更新完成后,可以通过db.runCommand({getLastError:1})来获取更新了多少文档。

    参考:MongoDB权威指南

  • 相关阅读:
    R语言使用RMySQL连接及读写Mysql数据库
    sparkR介绍及安装
    信息熵的计算
    django学习-管理界面、视图
    django学习-数据库操作接口API--(CRUD)
    django学习-数据库配置-创建模型
    django学习-安装、创建应用、编写视图
    接口八问 & 接口测试质量评估标准
    robotframework-post request请求携带上一个请求返回的cookie
    pipenv安装包时一直卡在Locking [packages] dependencies…,换pypi源
  • 原文地址:https://www.cnblogs.com/tian2010/p/2603832.html
Copyright © 2020-2023  润新知