MongoDB 文档管理

本章节我们将向大家介绍如何对 MongoDB 集合中的文档进行 CRUD 操作。MongoDB 文档的数据结构和 JSON 基本一样,所有存储在集合中的数据都是 BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

插入文档

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,在 MongoDB 3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany() 方法。

insert()

语法格式:

db.COLLECTION_NAME.insert(document)

示例:

# 插入一条到 col 集合
test> db.col.insert({name:"insert"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6e2fd10366fa87109a123") }
}

# 重复插入一条数据到 col 集合
# MongoDB 插入的数据会自动创建一个 _id 字段,该字段是唯一的,相当于主键
test> db.col.insert({_id:ObjectId("64e6e2fd10366fa87109a123"), name:"insert"})
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: test.col index: _id_ dup key: { _id: ObjectId('64e6e2fd10366fa87109a123') }
...

# 查看 col 集合数据
test> db.col.find()
[
 { _id: ObjectId("64e6e2fd10366fa87109a123"), name: 'insert' },
 { _id: '64e6e2fd10366fa87109a123', name: 'insert' }
]

注意:若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。

我们也可以将数据定义为一个变量,如下所示:

test> doc=({title: 'MongoDB 教程',  url: 'https://www.hxstrive.com' })
{ title: 'MongoDB 教程', url: 'https://www.hxstrive.com' }

执行插入操作:

test> db.col.insert(doc)
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6e17f10366fa87109a11f") }
}

插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

save() 新版本中已废弃

语法格式:

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

参数说明:

• document:文档数据。

• writeConcern:可选,抛出异常的级别。

示例:

# 方法已废弃了
test> db.col.save({name:"hello world", type:"msg"})
TypeError: db.col.save is not a function

注意:如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法在新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。

insertOne()

insertOne() 用于向集合插入一个新文档,语法格式:

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

参数说明:

  • document:要写入的文档。

  • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。

示例:

#  插入单条数据
test> db.col2.insertOne({name:"插入一条"})
{
 acknowledged: true,
 insertedId: ObjectId("64e6e22e10366fa87109a120")
}

# 查看插入的数据
test> db.col2.find()
[ { _id: ObjectId("64e6e22e10366fa87109a120"), name: '插入一条' } ]

insertMany()

db.collection.insertMany() 用于向集合插入一个多个文档,语法格式:

db.collection.insertMany(
  [ <document 1> , <document 2>, ... ],
  {
     writeConcern: <document>,
     ordered: <boolean>
  }
)

参数说明:

  • document:要写入的文档。

  • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。

  • ordered:指定是否按顺序写入,默认 true,按顺序写入。

示例:

#  插入多条数据
test> db.col3.insertMany([{name:"插入多条1"}, {name:"插入多条2"}])
{
 acknowledged: true,
 insertedIds: {
   '0': ObjectId("64e6e25710366fa87109a121"),
   '1': ObjectId("64e6e25710366fa87109a122")
 }
}

# 查看插入的数据
test> db.col3.find()
[
 { _id: ObjectId("64e6e25710366fa87109a121"), name: '插入多条1' },
 { _id: ObjectId("64e6e25710366fa87109a122"), name: '插入多条2' }
]

更新文档

MongoDB 使用 update() 和 save() 方法来更新集合中的文档。

update()

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(
  <query>,
  <update>,
  {
    upsert: <boolean>,
    multi: <boolean>,
    writeConcern: <document>
  }
)

参数说明:

  • query:update 的查询条件,类似 sql update 查询内 where 后面的。

  • update:update 的对象和一些更新的操作符(如 $, $inc...)等,也可以理解为 sql update 查询内 set 后面的

  • upsert:可选,这个参数的意思是,如果不存在 update 的记录,是否插入 objNew, true 为插入,默认是 false,不插入。

  • multi:可选,mongodb 默认是 false, 只更新找到的第一条记录,如果这个参数为 true, 就把按条件查出来多条记录全部更新。

  • writeConcern:可选,抛出异常的级别。

示例:

# 插入一条数据到 col 集合
test> db.col.insert({name:"hello world", type:"msg"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6e73010366fa87109a124") }
}

# 如果 type="msg",则将 name 更新为 “hello mongodb”
test> db.col.update({type:"msg"}, {$set:{name:"hello mongodb"}})
{
 acknowledged: true,
 insertedId: null,
 matchedCount: 1,
 modifiedCount: 1,
 upsertedCount: 0
}

# 查询 col 集合数据
test> db.col.find()
[
 {
   _id: ObjectId("64e6e73010366fa87109a124"),
   name: 'hello mongodb',
   type: 'msg'
 }
]

以上的 update 语句只会修改第一条匹配的文档,如果你要修改多条匹配的文档,则需要设置 multi 参数为 true。如:

test> db.col.update({type:"msg"}, {$set:{name:"hello mongodb"},{multi:true})

下面是更多关于 update 的实例:

# 只更新第一条记录
db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );

# 全部更新
db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} }, false, true );

# 只添加第一条
db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} }, true, false );

# 全部添加进去
db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} }, true, true );

# 全部更新
db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} }, false, true );

# 只更新第一条记录
db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} }, false, false );

删除文档

MongoDB 使用 remove() 函数移除集合中的数据,在执行 remove() 函数前先执行 find() 命令来判断执行的条件是否正确,这是一个比较好的习惯。

remove() 方法的基本语法格式如下所示:

db.collection.remove(
  <query>,
  <justOne>
)

如果你的 MongoDB 是 2.6 版本以后的,语法格式如下:

db.collection.remove(
  <query>,
  {
    justOne: <boolean>,
    writeConcern: <document>
  }
)

参数说明:

  • query:(可选)删除的文档的条件。

  • justOne: (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。

  • writeConcern:(可选)抛出异常的级别。

示例:

# 准备数据,插入三个文档到 col 集合
test> db.col.insert({name:"mongo", type:"mongodb"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6eaad10366fa87109a125") }
}
test> db.col.insert({name:"mongod", type:"mongodb"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6eab010366fa87109a126") }
}
test> db.col.insert({name:"mongos", type:"mongodb"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6eab310366fa87109a127") }
}

# 查看 col 集合中的数据
test> db.col.find()
[
 {
   _id: ObjectId("64e6eaad10366fa87109a125"),
   name: 'mongo',
   type: 'mongodb'
 },
 {
   _id: ObjectId("64e6eab010366fa87109a126"),
   name: 'mongod',
   type: 'mongodb'
 },
 {
   _id: ObjectId("64e6eab310366fa87109a127"),
   name: 'mongos',
   type: 'mongodb'
 }
]

# 删除 type 为 mongodb 的文档
test> db.col.remove({type:"mongodb"})
DeprecationWarning: Collection.remove() is deprecated. Use deleteOne, deleteMany, findOneAndDelete, or bulkWrite.
{ acknowledged: true, deletedCount: 3 }

# 查看集合数据,已经是空集合
test> db.col.find()

如果你只想删除第一条找到的记录可以设置 justOne 为 1,如下所示:

db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)

如果你想删除所有数据,可以使用以下方式(类似常规 SQL 的 truncate 命令):

db.col.remove({})

注意:remove() 虽然继续可以使用,但是已经过时了,官方推荐使用 deleteOne() 和 deleteMany() 方法。例如:

# 如删除集合下全部文档:
db.inventory.deleteMany({})

# 删除 status 等于 A 的全部文档:
db.inventory.deleteMany({ status : "A" })

# 删除 status 等于 D 的第一个文档:
db.inventory.deleteOne( { status: "D" } )

查询文档

MongoDB 查询文档使用 find() 方法,find() 方法以非结构化的方式来显示所有文档。

MongoDB 查询数据的语法格式如下:

db.collection.find(query, projection)

参数说明:

  • query:可选,使用查询操作符指定查询条件。

  • projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

>db.col.find().pretty()

pretty() 方法以格式化的方式来显示所有文档。

示例:

# 准备一条数据
test> db.col.insert({name:"mongo", type:"mongodb"})
{
 acknowledged: true,
 insertedIds: { '0': ObjectId("64e6ed5410366fa87109a128") }
}

# 查看数据
test> db.col.find().pretty()
[
 {
   _id: ObjectId("64e6ed5410366fa87109a128"),
   name: 'mongo',
   type: 'mongodb'
 }
]

注意:除了 find() 方法之外,还有一个 findOne() 方法。但是,MongoDB 推出的 MongoDB Shell 查询自动就进行格式化了。

MongoDB 与 RDBMS Where 语句比较

如果你熟悉常规的 SQL 语句,通过下表可以更好的理解 MongoDB 的条件语句查询:

MongoDB 文档管理

AND 条件

MongoDB 的 find() 方法可以传入多个键 (key),每个键 (key) 以逗号隔开,即常规 SQL 的 AND 条件。

语法格式如下:

db.col.find({
   key1:value1,
   key2:value2
})

示例

# 准备点数据
test> db.col.insert({name:"mongo", type:"mongodb"})
test> db.col.insert({name:"mongos", type:"mongodb"})
test> db.col.insert({name:"mongod", type:"mongodb"})
test> db.col.insert({name:"shell", type:"mongodb"})

# 查询 type 为 mongodb 且 name 为 mongo 的数据
test> db.col.find({type:"mongodb",name:"mongo"})
[
 {
   _id: ObjectId("64e6ed5410366fa87109a128"),
   name: 'mongo',
   type: 'mongodb'
 }
]

以上示例类似 WHERE 语句:WHERE type='mongodb' AND name='mongo'

OR 条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

db.col.find(
  {
     $or: [
         {key1: value1}, {key2:value2}
     ]
  }
)

示例

# 准备点数据
test> db.col.insert({name:"mongo", type:"mongodb"})
test> db.col.insert({name:"mongos", type:"mongodb"})
test> db.col.insert({name:"mongod", type:"mongodb"})
test> db.col.insert({name:"shell", type:"mongodb"})

# 查询 name 为 mongod 或 mongos 的文档
test> db.col.find({$or:[{name:"mongod"}, {name:"mongos"}]})
[
 {
   _id: ObjectId("64e6ee6310366fa87109a129"),
   name: 'mongos',
   type: 'mongodb'
 },
 {
   _id: ObjectId("64e6ee6710366fa87109a12a"),
   name: 'mongod',
   type: 'mongodb'
 }
]

以上示例类似 WHERE 语句:WHERE name='mongod' AND name='mongos'

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 

where type='mongodb' AND (name='mongod' AND name='mongos')

示例:

# 准备点数据
test> db.col.insert({name:"mongo", type:"mongodb"})
test> db.col.insert({name:"mongos", type:"mongodb"})
test> db.col.insert({name:"mongod", type:"mongodb"})
test> db.col.insert({name:"shell", type:"mongodb"})

# 查询 type 为 mongodb,且 name 为 mongod 或 mongos 的文档
test> db.col.find({type:"mongodb", $or:[{name:"mongod"}, {name:"mongos"}]})
[
 {
   _id: ObjectId("64e6ee6310366fa87109a129"),
   name: 'mongos',
   type: 'mongodb'
 },
 {
   _id: ObjectId("64e6ee6710366fa87109a12a"),
   name: 'mongod',
   type: 'mongodb'
 }
]
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号