美文网首页
MongoDB 快速入门实战教程基础篇 一 :文档的 UD操作

MongoDB 快速入门实战教程基础篇 一 :文档的 UD操作

作者: you的日常 | 来源:发表于2022-01-06 09:41 被阅读0次

    前一部分的文章:
    MongoDB 快速入门实战教程基础篇 一 :文档的 CR操作


    Update Operations

    MongoDB 提供了几个方法用于更新文档,它们分别是:

    db.collection.updateOne(<filter>, <update>, <options>)
    db.collection.updateMany(<filter>, <update>, <options>)
    db.collection.replaceOne(<filter>, <update>, <options>)
    
    

    更新单个文档

    updateOne() 方法会根据过滤器更新集合中的单个文档,其语法格式如下:

    db.collection.updateOne(
       <filter>,
       <update>,
       {
         upsert: <boolean>,
         writeConcern: <document>,
         collation: <document>,
         arrayFilters: [ <filterdocument1>, ... ]
       }
    )
    
    

    例如将 inven 集合中名为 韦德 的球员名称改为 热火韦德,对应示例如下:

    > db.inven.updateOne(
    ... {name: "韦德"}, 
    ... {$set: {name: "热火韦德"}}
    ... )
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    
    

    返回的结果文档包含操作状态 acknowledged,匹配的文档数 matchedCount 和修改过的文档数 modifiedCount。本次返回结果文档代表修改成功,韦德 的名字被改变了。

    Upsert

    在实际应用中,upsert 指令非常常见。当 upsert 的值为 true 时,如果 <filter> 并匹配到文档,那么本次操作就会将它当作新文档添加到集合中。例如当文档中没有名为 ABC 的球员时,会将 奥尼尔 添加到集合中,对应示例如下:

    > db.inven.updateOne( {name: "ABC"}, {$set: {name: "奥尼尔"}}, {upsert: true})
    {
        "acknowledged" : true,
        "matchedCount" : 0,
        "modifiedCount" : 0,
        "upsertedId" : ObjectId("5d15d6c718f0856b4385c123")
    }
    
    

    结果文档显示本次操作未匹配到文档,也未更新文档,但操作成功。相对于上一次的结果文档,本次结果文档中多出了 upsertedId,这正是 奥尼尔 文档的 _id。我们可以通过 find() 方法来验证:

    > db.inven.find({name: "奥尼尔"})
    { "_id" : ObjectId("5d15d6c718f0856b4385c123"), "name" : "奥尼尔" }
    
    

    果然, 奥尼尔 被添加到集合中。

    更新多个文档

    updateMany() 方法可以更新多个文档,其语法格式与 updateOne() 相同。假设要将球衣号大于 20 的所有球员球衣号设置为 33,对示例如下:

    > db.inven.updateMany(
    ... {number: {$gt: 20}},
    ... {$set: {number: 33}}
    ... )
    { "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
    
    

    其他指令如 upsert 使用时与之前相同。

    update() 方法的语法格式与 updateOne() 相同,但它默认只更新单个文档。假设要将球衣号等于 33 的球员球衣号设置为 0,对应示例如下:

    > db.inven.update( {number: {$eq: 33}}, {$set: {number: 0}} )
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    
    

    返回文档显示只更新了 1 个文档,其他查询符合条件的文档并未被更新。如果想要更新多个文档,可以将指令 multi 设置为 true,或者使用 updateMany()

    替换文档

    replaceOne() 方法会根据过滤器替换集合中的单个文档,其语法如下:

    db.collection.replaceOne(
       <filter>,
       <replacement>,
       {
         upsert: <boolean>,
         writeConcern: <document>,
         collation: <document>
       }
    )
    
    

    假设要为 奥尼尔 添加球衣号,对应示例如下:

    > db.inven.replaceOne( {name: "奥尼尔"}, {name: "奥尼尔", number: 34})
    { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
    
    

    命令执行后,奥尼尔 文档从 {name: "奥尼尔"} 变成了 {name: "奥尼尔", number: 34}

    Save

    save() 是一个多用途的方法,它会根据 _id 是否存在而选择调用 insert() 或者 update()。当文档中存在 _id 时,save() 等效于带有 upsert 指令的 update();当文档中不包含 _id 时,save() 等效于 insert(),此时 MongoShell 将创建一个 ObjectId,并将其分配给 _idsave() 的语法格式如下:

    db.collection.save(
       <document>,
       {
         writeConcern: <document>
       }
    )
    
    

    奥尼尔_idObjectId("5d16c699dca60c968c6d8f69"),当 save() 方法中的文档包含 _id 时会更新文档内容,对应示例如下:

    > db.inven.save({_id: "5d16c699dca60c968c6d8f69", name: "奥尼尔", status: "R"})
    WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : "5d16c699dca60c968c6d8f69"
    })
    
    

    {"name" : "奥尼尔" } 变成了 {"name" : "奥尼尔", "status" : "R" }。要注意的是,ObjectId("5d16c699dca60c968c6d8f69") 在命令中的写法是 "5d16c699dca60c968c6d8f69"

    更新操作符

    MongoDB 共有四类更新操作符,它们是:字段更新操作符、数组更新操作符、修饰操作符和按位操作符。

    字段更新操作符

    MongoDB 中共有 9 个字段更新操作符,它们分别是:

    名称 描述
    $currentDate 将字段的值设置为当前日期,可以是 DateTimestamp
    $inc 将指定字段的值与传入的值相加。
    $min 仅当指定的值小于现有字段值时才更新字段。
    $max 仅当指定的值大于现有字段值时才更新字段。
    $mul 将指定字段的值与传入的值相乘。
    $rename 重命名字段。
    $set 设置文档中字段的值。
    $setOnInsert 如果更新导致文档插入,则设置字段的值。对修改现有文档的更新操作没有影响。
    $unset 从文档中删除指定的字段。

    我们将在本节中挑选几个典型的字段更新操作符进行学习,对于作用相似或语法类似的将不作赘述。例如 $min$max,我们只需要了解其中一个即可。

    currentDate

    $currentDate 的作用是将字段的值设为当前日期,其语法格式如下:

    { $currentDate: { <field1>: <typeSpecification1>, ... } }
    
    

    其中,<typeSpecification1> 可以是一个布尔值、 {$type: "timestamp"} 或者 {$type: "date"}。在开始学习之前,我们需要准备以下数据:

    > db.registers.save({_id: 1, name: "async", pwd: "123456", regTime: new Date()})
    
    

    此时,regTime 的值为 ISODate("2019-07-10T08:40:02.253Z")。假设要更新 regTime的值,我们可以使用如下命令:

    > db.registers.update(
    ... {_id: 1},
    ... {$currentDate:{regTime: true}
    ... })
    
    

    命令执行后,regTime 的值就会被改变,新的文档内容类似于:

    { "_id" : 1, "name" : "async", "pwd" : "123456", "regTime" : ISODate("2019-07-10T08:43:24.981Z") }
    
    

    当然,我们也可以使用 {$type: "timestamp"} 这种语法,命令如下:

    > db.registers.update( 
    ... {_id: 1}, 
    ... {$currentDate:{ regTime: {$type: "timestamp"}} 
    ... })
    
    

    命令执行后,regTime 的值也会被改变。要注意的是,由于 DateTimestamp 格式不同,所以 regTime 的值的格式将由原来的 ISODate 变成 Timestamp

    inc

    $inc 的作用是按指定的数量增加字段的值,其语法格式如下:

    { $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
    
    

    假设现在有一个这样的文档:

    {
      _id: 1,
      sku: "abc123",
      quantity: 10,
      metrics: {
        orders: 2,
        ratings: 3.5
      }
    }
    
    

    如果我们需要在此基础上将 quantitymetrics.orders 的值做加法,对应示例如下:

    db.products.update(
       { sku: "abc123" },
       { $inc: { quantity: -2, "metrics.orders": 1 } }
    )
    
    

    命令执行后,文档将会变成下面这样:

    {
       "_id" : 1,
       "sku" : "abc123",
       "quantity" : 8,
       "metrics" : {
          "orders" : 3,
          "ratings" : 3.5
       }
    }
    
    

    如果传入的不是数字,而是字符串或其它类型,我们将得到错误提示:

    > db.products.update({sku: "abc123" },{$inc: {quantity: "async"}})
    WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
            "code" : 14,
            "errmsg" : "Cannot increment with non-numeric argument: {quantity: \"async\"}"
        }
    })
    
    

    $mul 的作用是将指定字段的值与传入的值相乘,这与 $inc 类似,此处不再赘述。$mul 的语法和介绍可查阅官方文档 $mul

    min

    $min 的描述是“仅当指定的值小于现有字段值时才更新字段”,其语法格式如下:

    { $min: { <field1>: <value1>, ... } }
    
    

    假设有以下数据:

    { _id: 1, highScore: 800, lowScore: 200 }
    
    

    最高分 highScore800,最低分 lowScore200。以下 $min 操作将用指定的 150200 进行比对,由于 150 < 200,原文档中 lowScore 的值会被更新为指定的 150。更新语句如下:

    > db.scores.update( { _id: 1 }, { $min: { lowScore: 250 } } )
    
    

    命令执行后,文档将会变成:

    { _id: 1, highScore: 800, lowScore: 150 }
    
    

    示例中只演示了数字类型的比较,实际上 BSON 都可以进行比较,比较顺序参考 BSON comparison order$max 将指定值与现有字段值进行比较,如果指定值大于现有字段值,则更新对应字段值。这与 $min 类似,此处不再赘述。$max 的语法和介绍可查阅官方文档 $max

    unset

    相关文章

      网友评论

          本文标题:MongoDB 快速入门实战教程基础篇 一 :文档的 UD操作

          本文链接:https://www.haomeiwen.com/subject/vryhcrtx.html