关于mongodb:MongoDB-新手入门-CRUD

31次阅读

共计 8857 个字符,预计需要花费 23 分钟才能阅读完成。

本文是 MongoDB 新手入门 系列的第一篇,在本文中,咱们将会解说 MongoDB 根本的增删改查操作,在学习完本文后,读者将会把握对 MongoDB 的汇合文档进行根本的新增,批改,删除以及基于多种条件的查问操作。

本文将会继续修改和更新,最新内容请参考我的 GITHUB 上的 程序猿成长打算 我的项目,欢送 Star,更多精彩内容请 follow me。

插入文档

在 MongoDB shell 中,插入文档有以下两个办法:

  • 应用 db.collection.insertOne() 插入单个文档
  • 应用 db.collection.insertMany() 插入多个文档

在插入文档时,如果 collection 不存在,插入操作将会主动创立 collection。如果文档没有 _id 字段,MongoDB 将会主动增加一个 _id 字段,类型为 ObjectId

在 MongoDB 中,每一个文档都须要一个惟一的 _id 字段作为主键,如果插入时没有指定 _id 字段,MongoDB 驱动将会主动生成一个类型为 ObjectId_id 字段。

ObjectId 是一种可能疾速生成的,有序的,12 字节大小的惟一值,蕴含:

  • 一个 4 字节的工夫戳,代表了 ObjectId 的创立工夫,取值为 Unix 工夫戳(秒)
  • 一个 5 字节的随机值,该值每个过程都只会生成一次,对每台服务器和过程来说该值是惟一的
  • 一个 3 字节的自增值,初始为一个随机数
use sample_mflix

// 插入单个文档
db.movies.insertOne(
  {
    title: "The Favourite",
    genres: ["Drama", "History"],
    runtime: 121,
    rated: "R",
    year: 2018,
    directors: ["Yorgos Lanthimos"],
    cast: ["Olivia Colman", "Emma Stone", "Rachel Weisz"],
    type: "movie"
  }
)

// 插入多个文档
db.movies.insertMany([
   {
      title: "Jurassic World: Fallen Kingdom",
      genres: ["Action", "Sci-Fi"],
      runtime: 130,
      rated: "PG-13",
      year: 2018,
      directors: ["J. A. Bayona"],
      cast: ["Chris Pratt", "Bryce Dallas Howard", "Rafe Spall"],
      type: "movie"
    },
    {
      title: "Tag",
      genres: ["Comedy", "Action"],
      runtime: 105,
      rated: "R",
      year: 2018,
      directors: ["Jeff Tomsic"],
      cast: ["Annabelle Wallis", "Jeremy Renner", "Jon Hamm"],
      type: "movie"
    }
])

除了罕用的 insertOneinsertMany 办法之外,还能够用以下形式插入文档

  • db.collection.bulkWrite()
  • 配合 upsert: true 选项

    • db.collection.updateOne()
    • db.collection.updateMany()
    • db.collection.findAndModify()
    • db.collection.findOneAndUpdate()

查问文档

最根本的查询方法是 db.collection.find()db.collection.findOne(),在 MongoDB 中插入以下文档

db.inventory.insertMany([{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm"}, status: "A" },
   {item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in"}, status: "A" },
   {item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in"}, status: "D" },
   {item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm"}, status: "D" },
   {item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm"}, status: "A" }
]);

查问 Collection 中所有文档

// 等价 SQL:SELECT * FROM inventory
db.inventory.find({})
// 等价 SQL:SELECT * FROM inventory LIMIT 1
db.inventory.findOne({})

指定查问条件

等值查问

// 等价 SQL:SELECT * FROM inventory WHERE status = "D"
db.inventory.find({status: "D"})
// 等价 SQL:SELECT * FROM inventory WHERE status != "D"
db.inventory.find({status: { $ne: "D"} })

IN 查问

// 等价 SQL:SELECT * FROM inventory WHERE status in ("A", "D")
db.inventory.find({status: { $in: ["A", "D"]}})
// 等价 SQL: SELECT * FROM inventory WHERE status NOT IN ("A", "D")
db.inventory.find({status: { $nin: ["A", "D"] } })

范畴查问

// SQL: SELECT * FROM inventory WHERE qty >= 50 AND qty < 100
db.inventory.find({qty: { $gte: 50, $lt: 100} })

比拟操作符反对这些:$lt$gt$gte$lte

AND 查问

// SQL:SELECT * FROM inventory WHERE status = "A" AND qty < 30
db.inventory.find({status: "A", qty: { $lt: 30} })

OR 查问

// SQL:SELECT * FROM inventory WHERE status = "A" OR qty < 30
db.inventory.find({$or: [ { status: "A"}, {qty: { $lt: 30} } ] })

同时应用 AND 和 OR

// SQL: SELECT * FROM inventory WHERE status = "A" AND (qty < 30 OR item LIKE "p%")
db.inventory.find({
  status: "A",
  $or: [{ qty: { $lt: 30} }, {item: /^p/} ]
})

NOT

// 查问 qty 模 5 值为 1 的所有文档,这里匹配的 qty 可能值为 1,6,11,16 等
db.inventory.find({qty: { $mod: [5, 1] } })
// 查问 qty 模 5 值部位 1 的所有文档,可能值为 2, 3, 4, 5, 7, 8, 9, 10, 12 等
db.inventory.find({qty: { $not: { $mod: [5, 1] } } })

查问嵌套的文档

查问所有 size 等于 {h: 14, w: 21, uom: "cm"} 的文档

db.inventory.find({ size: { h: 14, w: 21, uom: "cm"} } )

查问所有 sizeuom 等于 in 的文档

db.inventory.find({ "size.uom": "in"} )

查问数组

在 MongoDB 中插入以下文档

db.inventory.insertMany([{ item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [14, 21] },
   {item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [14, 21] },
   {item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [14, 21] },
   {item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [22.85, 30] },
   {item: "postcard", qty: 45, tags: ["blue"], dim_cm: [10, 15.25] }
]);

上面的示例查问所有字段 tags 值只蕴含元素 “red” 和 “blank”(程序统一)的文档

db.inventory.find({tags: ["red", "blank"]})

如果只是查问同时蕴含 “red” 和 “blank” 两个值,并且不关怀排序或者数组中是否蕴含其它元素,则能够应用 $all 操作符

db.inventory.find({tags: { $all: ["red", "blank"] } })

查问 tags 蕴含 “red” 的文档

db.inventory.find({tags: "red"})

查问所有 dim_cm 蕴含至多一个大于值 25 的所有文档

db.inventory.find({dim_cm: { $gt: 25} })

查问所有 dim_cm 蕴含至多一个值大于 15 或者 小于 20 的所有文档

db.inventory.find({dim_cm: { $gt: 15, $lt: 20} })

查问所有 dim_cm 蕴含至多一个值大于 22 且小于 30 的所有文档

db.inventory.find({dim_cm: { $elemMatch: { $gt: 22, $lt: 30} } })

查问数组 dim_cm 的第二个值大于 25

db.inventory.find({"dim_cm.1": { $gt: 25}})

查问数组 tags 领有 3 个元素的所有文档

db.inventory.find({"tags": { $size: 3} })

查问返回指定字段

默认状况下,MongoDB 的查问会返回匹配文档中所有的字段,通过 projection 能够返回指定的字段。

返回指定字段

// SQL: SELECT _id, item, status FROM inventory WHERE status = "A"
db.inventory.find({status: "A"}, {item: 1, status: 1})

查问后果中会主动返回 _id 字段,能够通过设置 _id: 0 来被动打消该字段。

// SQL:SELECT item, status FROM inventory WHRE status = "A"
db.inventory.find({ status: "A"}, {item: 1, status: 1, _id: 0} )

排除指定字段

db.inventory.find({status: "A"}, {status: 0, instock: 0})

返回数组中指定元素

应用 $slice 操作符返回 instock 数组中最初一个元素

db.inventory.find({status: "A"}, {item: 1, status: 1, instock: { $slice: -1} })

查问值为 NULL 或者缺失字段

在 MongoDB 中,不同的查问操作符对 null 的解决形式是不同的。在 MongoDB 中插入以下文档

db.inventory.insertMany([{ _id: 1, item: null},
   {_id: 2}
])

等值查问

查问 item 值为 null 或者不蕴含 item 字段的所有文档

db.inventory.find({item: null})

类型查看

查问所有 item 值为 null 的文档

db.inventory.find({item: { $type: 10} })

这里的 $type = 10 对应了 BSON 类型 Null

存在性查看

查问所有不蕴含字段 item 的文档

db.inventory.find({item: { $exists: false} })

查问所有蕴含 item 字段,然而值为 null 的文档

db.inventory.find({item: { $eq: null, $exists: true} })

限度查问后果数量

// 只查问 3 条数据
db.inventory.find({}).limit(3)
// 从第 2 条开始,查问 3 条数据
db.inventory.find({}).limit(3).skip(2)

排序

排序方向 1 为正序,-1 为倒序。

db.inventory.find({}).sort({item: 1, qty: -1})

查问汇合中的文档数量

该办法用于查问匹配条件的文档数量,语法为

db.collection.count(query, options)

示例

db.orders.count({ ord_dt: { $gt: new Date('01/01/2012') } } )

查问字段的惟一值 distinct

查问汇合中字段的惟一值,语法为

db.collection.distinct(field, query, options)

附录:反对的查问操作符

类别 操作符 用处
Comparison $eq 等值判断
Comparison $gt 大于某个值
Comparison $gte 大于等于某个值
Comparison $in 以后值在数组中
Comparison $lt 小于某个值
Comparison $lte 小于等于某个值
Comparison $ne 不等于某个值
Comparison $nin 以后值不再数组中
Logical $and AND
Logical $not 反转查问条件
Logical $nor 所有查问条件都不匹配
Logical $or OR
Element $exists 字段存在性查看
Element $type 字段类型查看
Evaluation $expr 在查问表达式中应用聚合语法
Evaluation $jsonSchema 验证文档合乎指定的 JSON 模型
Evaluation $mod 对字段值进行取模运算
Evaluation $regex 抉择匹配正则表达式的文档
Evaluation $text 执行文本搜寻
Evaluation $where JavaScript 表达式匹配
Geospatial $geoIntersects 地理坐标匹配
Geospatial $geoWithin 地理坐标匹配
Geospatial $near 地理坐标匹配
Geospatial $nearSphere 地理坐标匹配
Array $all 匹配蕴含查问中指定的所有元素的数组
Array $elemMatch 数组中的元素匹配表达式则返回文档
Array $size 抉择数组大小为 size 的文档
Bitwise $bitsAllClear 二进制匹配
Bitwise $bitsAllSet 二进制匹配
Bitwise $bitsAnyClear 二进制匹配
Bitwise $bitsAnySet 二进制匹配
Miscellaneous $comment 在查问中增加正文
Miscellaneous $rand 随机生成一个 0-1 之间的浮点值

更新文档

罕用的文档更新办法有以下三种

  • db.collection.updateOne(<filter>, <update>, <options>) 更新单个文档
  • db.collection.updateMany(<filter>, <update>, <options>) 更新多个文档
  • db.collection.replaceOne(<filter>, <update>, <options>) 替换单个文档

咱们这里以 updateOne() 办法为例进行解说,updateOne() 办法的语法如下

db.collection.updateOne(
   <filter>, // 要更新的文档筛选条件
   <update>, // 文档更新命令
   {
     upsert: <boolean>, // 设置为 true 时,如果 filter 没有匹配到文档,则主动新增文档
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [<filterdocument1>, ...],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)

更新 item=paper 的文档

db.inventory.updateOne({ item: "paper"},
   {$set: { "size.uom": "cm", status: "P"},
     $currentDate: {lastModified: true}
   }
)

更新操作符如下

  • $set 操作符指定了要更新匹配文档的 size.uomcmstatusp
  • $currentDate 操作符用于更新 lastModified 字段为以后的日期,如果 lastModified 字段不存在,则主动创立

更新文档,如果不存在则新增

db.restaurant.updateOne({ "name" : "Pizza Rat's Pizzaria"},
    {$set: {"_id" : 4, "violations" : 7, "borough" : "Manhattan"} },
    {upsert: true}
);

更多字段操作符如下

操作符 用处
$currentDate 设置字段值为当日期,能够是日期或者是工夫戳
$inc 将字段的值加上某个数值
$min 只有指定的值小于曾经存在的值时才更新
$max 只有指定的额值大于曾经存在的值才更新
$mul 将字段的值乘以某个数值
$rename 重命名指定字段
$set 设置文档中要更新的字段值
$setOnInsert 如果以后操作新增了文档,则设置字段的值。如果更新操作只是批改一个曾经存在的文档,则该操作符有效
$unset 从文档中移除指定字段

除了罕用的三个办法,还有以下办法也能够用于更新文档

  • db.collection.findOneAndReplace().
  • db.collection.findOneAndUpdate().
  • db.collection.findAndModify().
  • db.collection.bulkWrite().

删除文档

在 MongoDB 中,通常应用以下办法删除文档

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

删除所有为文档

db.inventory.deleteMany({})

删除所有匹配条件的文档

db.inventory.deleteMany({status : "A"})

删除匹配条件的一个文档

db.inventory.deleteOne({ status: "D"} )

除了罕用的两个办法外,还能够用以下办法删除文档

  • db.collection.findOneAndDelete().

    findOneAndDelete() 提供了一个 sort 选项,该选项容许删除依照指定排序规定排序后匹配的第一个文档

  • db.collection.findAndModify().

    db.collection.findAndModify() 提供了一个 sort 选项,该选项容许删除依照指定排序规定排序后匹配的第一个文档

  • db.collection.bulkWrite().

批量写操作

MongoDB 提供了一种对单个 Collection 执行批量写入的操作能力,应用 db.collection.bulkWrite() 办法实现批量的插入、更新和删除操作。

有序和无序操作

批量写操作能够试有序的(ordered)或者无序(unordered)的,对于有序操作,MongoDB 会串行的执行操作,如果写操作过程中产生谬误,MongoDB 将会间接返回,前面的操作将不会被执行。无序操作则无奈保障这种行为,当产生谬误的时候,MongoDB 将会持续解决残余的文档。

对于分片的汇合来说,执行有序的批量操作通常会比较慢,因为每一个操作都必须期待上一个操作的实现。默认状况下,bulkWrite() 执行的是有序的操作,能够通过设置 ordered: false 选项来启用无序操作模式。

bulkWrite() 办法

bulkWrite() 反对以下写操作

  • insertOne
  • updateOne
  • updateMany
  • replaceOne
  • deleteOne
  • deleteMany

假如一个名为 characters 的汇合中蕴含上面的文档

{"_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4},
{"_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3},
{"_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3}

上面的 bulkWrite() 办法对该汇合执行多个操作

db.characters.bulkWrite(
   [
      { insertOne :
         {
            "document" :
            {"_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4}
         }
      },
      { insertOne :
         {
            "document" :
            {"_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3}
         }
      },
      { updateOne :
         {"filter" : { "char" : "Eldon"},
            "update" : {$set : { "status" : "Critical Injury"} }
         }
      },
      { deleteOne :
         {"filter" : { "char" : "Brisbane"} }
      },
      { replaceOne :
         {"filter" : { "char" : "Meldane"},
            "replacement" : {"char" : "Tanys", "class" : "oracle", "lvl" : 4}
         }
      }
   ]
);

操作返回以下内容

{
   "acknowledged" : true,
   "deletedCount" : 1,
   "insertedCount" : 2,
   "matchedCount" : 2,
   "upsertedCount" : 0,
   "insertedIds" : {
      "0" : 4,
      "1" : 5
   },
   "upsertedIds" : {}}

参考文档

  • MongoDB 官网文档

正文完
 0