5. MongoDB 文档插入、更新、删除、查询

1. 插入文档

文档的数据结构和JSON基本一样。所有存储在集合中的数据都是BSON格式。

BSON是一种类似JSON的二进制形式的存储格式,是Binary JSON的简称。常用的插入文档方法包括:

  • db.collection.insertOne():插入单个文档
  • db.collection.insertMany():插入多个文档
  • db.collection.save():类似于insertOne()。如果文档存在,则该文档会被更新;如果文档不存在,则会插入一个新文档。

1.1 insertOne()

insertOne() 方法用于在集合中插入单个文档。

db.collection.insertOne(document, options)

  • document:要插入的单个文档。
  • options(可选):一个可选参数对象,可以包含writeConcern和bypassDocumentValidation等
复制代码
db.myCollection.insertOne({
    name: "Alice",
    age: 25,
    city: "New York"
});


返回结果:
{
    "acknowledged": true,
    "insertId": ObjectId("60c72b2f9b1d8b5a5f8e2b2d")
}

1.2 insertMany()

insertMany()方法用于在集合中插入多个文档。

db.collection.insertMany(documents, options)

  • documents:要插入的文档数组
  • options(可选):一个可选参数对象,可以包含ordered、writeConcern和bypassDocumentValidation等。
sql 复制代码
db.myCollection.insertMany([
    { name: "Bob", age: 30, city: "Los Angeles" },
    { name: "Charlie", age: 35, city: "Chicago" }
]);


返回结果:
{
    "acknowledged": true,
    "insertedIds": [
        ObjectId("60c72b2f9b1d8b5a5f8e2b2e"),
        ObjectId("60c72b2f9b1d8b5a5f8e2b2f")
    ]
}

1.3 db.collection.save()

save() 方法在插入文档时表现得类似于 insertOne()。

如果文档包含 _id 字段且已存在,则该文档会被更新;如果文档不包含 _id 字段或 _id 不存在,则会插入一个新文档。

db.collection.save(document, options)

  • document:要保存的文档。
  • options(可选):一个可选参数对象,可以包含 writeConcern 等。
    插入文档时的选项:

这些方法的options参数通常可以包含 以下选项:

  • ordered(仅适用于insertMany):布尔值。如果为true,则按顺序插入文档,在遇到错误时停止;如果为false,则尝试插入所有文档,即使遇到错误也继续。默认值为true。
  • writeConcern:指定写操作的确认级别
  • bypassDocumentValidation:布尔值。如果为 true,则忽略集合的文档验证规则。

1.4 实例

通过这些方法,你可以灵活地将文档插入到 MongoDB 集合中,以满足各种应用场景的需求。

sql 复制代码
插入单个文档:
db.myCollection.insertOne({
    name: "Alice",
    age: 25,
    city: "New York"
});


插入多个文档:
db.myCollection.insertMany([
    { name: "Bob", age: 30, city: "Los Angeles" },
    { name: "Charlie", age: 35, city: "Chicago" }
]);


保存文档:
db.myCollection.save({
    _id: ObjectId("60c72b2f9b1d8b5a5f8e2b2d"),
    name: "David",
    age: 40,
    city: "San Francisco"
});
sql 复制代码
以下文档可以存储在 MongoDB 的 runoob 数据库 的 col 集合中:
>db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
})


以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。
查看已插入文档:
> db.col.find()
{ "_id" : ObjectId("56064886ade2f21f36b03134"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
> 


我们也可以将数据定义为一个变量,如下所示:
> document=({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
});


执行后显示结果如下:
{
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}


执行插入操作:
> db.col.insert(document)
WriteResult({ "nInserted" : 1 })
> 


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

2. 更新文档

updateOne()

updateMany()

replaceOne()

findOneAndUpdate()

2.1 updateOne()

用于更新匹配过滤器的单个文档。

db.collection.updateOne(filter, update, options)

  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options :可选参数对象,如 upsertarrayFilters 等。
sql 复制代码
db.myCollection.updateOne(
    { name: "Alice" },        //过滤条件
    { $set: { age: 26 } },    //更新操作
    { upsert: false },        //可选操作
);

2.2 updateMany()

用于更新所有匹配过滤器的文档。

db.collection.updateMany(filter, update, options)

  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options :可选参数对象,如 upsertarrayFilters 等。
sql 复制代码
db.myCollection.updateMany(
    { age: { $lt: 30 } },                //过滤条件
    { $set: { status: "active" } },      //更新操作
    { upsert: false }                    //可选参数
);

2.3 replaceOne()

用于替换匹配过滤器的单个文档,新的文档将完全替换旧的文档。

db.collection.replaceOne(fileter, replacement, options)

  • filter:用于查找文档的查询条件。
  • replacement:新的文档,将替换旧的文档。
  • options :可选参数对象,如 upsert 等。
sql 复制代码
db.myCollection.replaceOne(
    { name: "Bob" },            //过滤条件
    { name: "Bob", age: 31 }    //新文档
);

2.4 findOneAndUpdate()

用于查找并更新单个文档,可以选择返回更新前或更新后的文档。

db.collection.findOneAndUpdate(filter, update, options)

  • filter:用于查找文档的查询条件。
  • update:指定更新操作的文档或更新操作符。
  • options :可选参数对象,如 projectionsortupsertreturnDocument 等。
sql 复制代码
db.myCollection.findOneAndUpdate(
    { name: "Charlie" },            //过滤条件
    { $set: { age: 36 } },          //更新操作
    {returnDocument: "after" }      //可选参数,返回更新后的文档
);

选项参数

  • upsert:如果没有匹配的文档,是否插入一个新文档。
  • arrayFilters:当更新嵌套数组时,指定应更新的数组元素的条件。
  • collation:指定比较字符串时使用的排序规则。
  • returnDocument:在 findOneAndUpdate 中使用,指定返回更新前 ("before") 或更新后 ("after") 的文档。

2.5 实例

sql 复制代码
更新单个文档:
db.myCollection.updateOne(
    { name: "Alice" },
    { $set: { age: 26 } }
);

更新多个文档:
db.myCollection.updateMany(
    { age: { $lt: 30 } },
    { $set: { status: "active" } }
);

替换单个文档:
db.myCollection.replaceOne(
    { name: "Bob" },
    { name: "Bob", age: 31 }
);

查找并更新单个文档:
db.myCollection.findOneAndUpdate(
    { name: "Charlie" },
    { $set: { age: 36 } },
    { returnDocument: "after" }
);
sql 复制代码
替换了 _id 为 56064f89ade2f21f36b03136 的文档数据:
>db.col.save({
    "_id" : ObjectId("56064f89ade2f21f36b03136"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "Runoob",
    "url" : "http://www.runoob.com",
    "tags" : [
            "mongodb",
            "NoSQL"
    ],
    "likes" : 110
})


替换成功后,可以通过 find() 命令来查看替换后的数据
>db.col.find().pretty()
{
        "_id" : ObjectId("56064f89ade2f21f36b03136"),
        "title" : "MongoDB",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "Runoob",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "NoSQL"
        ],
        "likes" : 110
}
> 
sql 复制代码
只更新第一条记录:
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 
);

3. 删除文档

常用的删除文档方法包括 deleteOne()、deleteMany() 以及 findOneAndDelete()。

使用场景:

  • 数据清理:删除不再需要的旧数据或无效数据。
  • 数据修正:在数据修正过程中删除错误的或重复的文档。
  • 自动化任务:在自动化脚本或任务中,根据特定条件删除文档。

3.1 deleteOne()

用于删除匹配过滤器的单个文档。

db.collection.deleteOne(filter, options)

  • filter:用于查找要删除的文档的查询条件。
  • options(可选):一个可选参数对象。
sql 复制代码
db.myCollection.deleteOne({ name: "Alice" });

结果
{
    "acknowledged": true,
    "deletedCount": 1
}

3.2 deleteMany()

用于删除所有匹配过滤器的文档。

复制代码
db.collection.deleteMany(filter, options)
  • filter:用于查找要删除的文档的查询条件。
  • options(可选):一个可选参数对象。
sql 复制代码
db.myCollection.deleteMany({ status: "inactive" });

返回结果:
{
    "acknowledged": true,
    "deletedCount": 1
}

3.3 findOneAndDelete()

用于查找并删除单个文档,并可以选择返回删除的文档。

复制代码
db.collection.findOneAndDelete(filter, options)
  • filter:用于查找要删除的文档的查询条件。
  • options :可选参数对象,如 projectionsort 等。
sql 复制代码
db.myCollection.findOneAndDelete(
    { name: "Charlie" },
    { projection: { name: 1, age: 1 } }
);

!!findOneAndDelete 返回被删除的文档,如果找不到匹配的文档,则返回 null。

删除操作的选项

这些删除方法的 options 参数通常可以包含以下选项:

  • writeConcern:指定写操作的确认级别。
  • collation:指定比较字符串时使用的排序规则。
  • projection (仅适用于 findOneAndDelete):指定返回的字段。
  • sort (仅适用于 findOneAndDelete):指定排序顺序以确定要删除的文档。

3.4 实例

sql 复制代码
删除单个文档:
db.myCollection.deleteOne({ name: "Alice" });

删除多个文档:
db.myCollection.deleteMany({ status: "inactive" });

查找并删除单个文档:
db.myCollection.findOneAndDelete(
    { name: "Charlie" },
    { projection: { name: 1, age: 1 } }
);

4. 查询文档

4.1 查询方法

MongoDB 查询文档使用 find()、findOne() 方法。

find() 方法以非结构化的方式来显示所有文档。

4.1.1 find()

复制代码
db.collection.find(query, projection)
  • query :用于查找文档的查询条件。默认为 {},即匹配所有文档。
  • projection(可选):指定返回结果中包含或排除的字段。
sql 复制代码
查找所有文档:
db.myCollection.find();

按条件查找文档:
db.myCollection.find({ age: { $gt: 25 } });

按条件查找文档,并只返回指定字段:
db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);
sql 复制代码
需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
>db.col.find().pretty()


pretty() 方法以格式化的方式来显示所有文档。
db.col.find().pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

4.1.2 findOne()

用于查找集合中的单个文档。如果找到多个匹配的文档,它只返回第一个。

复制代码
db.collection.findOne(query, projection)
  • query :用于查找文档的查询条件。默认为 {},即匹配所有文档。
  • projection(可选):指定返回结果中包含或排除的字段。
sql 复制代码
查找单个文档:
db.myCollection.findOne({ name: "Alice" });


查找单个文档,并只返回指定字段:
db.myCollection.findOne(
    { name: "Alice" },
    { name: 1, age: 1, _id: 0 }
);

4.2 高级查询方法

4.2.1 使用比较操作符

MongoDB 支持多种比较操作符,如 gt、lt、gte、lte、eq、ne 等。

比较操作符有:

操作符 描述 示例
$eq 等于 { age: { $eq: 25 } }
$ne 不等于 { age: { $ne: 25 } }
$gt 大于 { age: { $gt: 25 } }
$gte 大于等于 { age: { $gte: 25 } }
$lt 小于 { age: { $lt: 25 } }
$lte 小于等于 { age: { $lte: 25 } }
$in 在指定的数组中 { age: { $in: [25, 30, 35] } }
$nin 不在指定的数组中 { age: { $nin: [25, 30, 35] } }
操作 格式 范例 RDBMS中的类似语句
等于 {<key>:<value>} db.col.find({"by":"菜鸟教程"}).pretty() where by = '菜鸟教程'
小于 {<key>:{$lt:<value>}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
小于或等于 {<key>:{$lte:<value>}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
大于 {<key>:{$gt:<value>}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
大于或等于 {<key>:{$gte:<value>}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
不等于 {<key>:{$ne:<value>}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50
sql 复制代码
查找年龄大于 25 的文档:
db.myCollection.find({ age: { $gt: 25 } });

4.2.2 使用逻辑操作符

MongoDB 支持多种逻辑操作符,如 and、or、not、nor 等。

逻辑操作符有:

操作符 描述 示例
$and 逻辑与,符合所有条件 { $and: [ { age: { $gt: 25 } }, { city: "New York" } ] }
$or 逻辑或,符合任意条件 { $or: [ { age: { $lt: 25 } }, { city: "New York" } ] }
$not 取反,不符合条件 { age: { $not: { $gt: 25 } } }
$nor 逻辑与非,均不符合条件 { $nor: [ { age: { $gt: 25 } }, { city: "New York" } ] }
sql 复制代码
查找年龄大于 25 且城市为 "New York" 的文档:
db.myCollection.find({
    $and: [
        { age: { $gt: 25 } },
        { city: "New York" }
    ]
});

4.2.3 使用正则表达式

可以使用正则表达式进行模式匹配查询。

sql 复制代码
查找名字以 "A" 开头的文档:
db.myCollection.find({ name: /^A/ });

4.2.4 投影

投影用于控制查询结果中返回的字段。可以使用包含字段和排除字段两种方式。

sql 复制代码
只返回名字和年龄字段:

db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);

4.2.5 排序

可以对查询结果进行排序。

sql 复制代码
按年龄降序排序:
db.myCollection.find().sort({ age: -1 });

4.2.6 限制与跳过

可以对查询结果进行限制和跳过指定数量的文档。

sql 复制代码
返回前 10 个文档:
db.myCollection.find().limit(10);

跳过前 5 个文档,返回接下来的 10 个文档:
db.myCollection.find().skip(5).limit(10);

4.2.7 实例

sql 复制代码
查找年龄大于 25 且城市为 "New York" 的文档,只返回名字和年龄字段,按年龄降序排序,并返回前 10 个文档。
db.myCollection.find(
    {
        $and: [
            { age: { $gt: 25 } },
            { city: "New York" }
        ]
    },
    { name: 1, age: 1, _id: 0 }
).sort({ age: -1 }).limit(10);

4.3 MongoDB AND 条件

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

语法格式如下:

复制代码
>db.col.find({key1:value1, key2:value2}).pretty()
sql 复制代码
通过 by 和 title 键来查询 菜鸟教程 中 MongoDB 教程 的数据

> db.col.find({"by":"菜鸟教程", "title":"MongoDB 教程"}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

以上实例中类似于 WHERE 语句:WHERE by='菜鸟教程' AND title='MongoDB 教程'

4.4 MongoDB OR 条件

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

复制代码
>db.col.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()
sql 复制代码
查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档。

>db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}
>

4.5 AND 和 OR 联合使用

sql 复制代码
以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 'where likes>50 AND (by = '菜鸟教程' OR title = 'MongoDB 教程')'

>db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

4.6 条件操作符

4.6.1 元素操作符

操作符 描述 示例
$exists 字段是否存在 { age: { $exists: true } }
$type 字段的 BSON 类型 { age: { $type: "int" } }

4.6.2 数组操作符

操作符 描述 示例
$all 数组包含所有指定的元素 { tags: { $all: ["red", "blue"] } }
$elemMatch 数组中的元素匹配指定条件 { results: { $elemMatch: { score: { $gt: 80, $lt: 85 } } } }
$size 数组的长度等于指定值 { tags: { $size: 3 } }

4.6.3 其他操作符

操作符 描述 示例
$regex 匹配正则表达式 { name: { $regex: /^A/ } }
$text 进行文本搜索 { $text: { $search: "coffee" } }
$where 使用 JavaScript 表达式进行条件过滤 { $where: "this.age > 25" }

4.7 $type操作符

在 MongoDB 中,type 操作符用于查询具有指定类型的字段的文档。MongoDB 的 type 操作符用于查询字段的 BSON 数据类型。允许指定一个或多个类型,并返回匹配这些类型的文档。

复制代码
db.collection.find({ field: { $type: <type> } })
  • field:要检查类型的字段。
  • type:指定的 BSON 类型,可以是类型的数字代码或类型名称的字符串。

4.7.1 BSON类型

常见的 BSON 类型及其对应的数字代码和字符串名称:

类型代码 类型名称
1 double
2 string
3 object
4 array
5 binData
6 undefined
7 objectId
8 bool
9 date
10 null
11 regex
12 dbPointer
13 javascript
14 symbol
15 javascriptWithScope
16 int
17 timestamp
18 long
19 decimal
255 minKey
127 maxKey

4.7.2 实例

sql 复制代码
查找字段类型为字符串的文档:
db.myCollection.find({ fieldName: { $type: "string" } })
或使用类型代码:
db.myCollection.find({ fieldName: { $type: 2 } })

查找字段类型为数字的文档,例如,查找 age 字段类型为整数的文档:
db.myCollection.find({ age: { $type: "int" } })
或使用类型代码:
db.myCollection.find({ age: { $type: 16 } })

查找字段类型为布尔值的文档:
db.myCollection.find({ isActive: { $type: "bool" } })
或使用类型代码:
db.myCollection.find({ isActive: { $type: 8 } })

查找字段类型为日期的文档:
db.myCollection.find({ createdAt: { $type: "date" } })
或使用类型代码:
db.myCollection.find({ createdAt: { $type: 9 } })

查找字段类型为多种类型的文档,例如,查找 value 字段类型为字符串或整数的文档:
db.myCollection.find({ value: { $type: ["string", "int"] } })
或使用类型代码:
db.myCollection.find({ value: { $type: [2, 16] } })
sql 复制代码
查找 details 字段类型为对象,并且 score 字段类型为双精度浮点数的文档:
db.myCollection.find({
    $and: [
        { details: { $type: "object" } },
        { score: { $type: "double" } }
    ]
})

或使用类型代码:
db.myCollection.find({
    $and: [
        { details: { $type: 3 } },
        { score: { $type: 1 } }
    ]
})
相关推荐
zzb15802 小时前
RAG from Scratch-优化-query
java·数据库·人工智能·后端·spring·mybatis
一只鹿鹿鹿3 小时前
信息安全等级保护安全建设防护解决方案(总体资料)
运维·开发语言·数据库·面试·职场和发展
堕2743 小时前
MySQL数据库《基础篇--数据库索引(2)》
数据库·mysql
wei_shuo3 小时前
数据库优化器进化论:金仓如何用智能下推把查询时间从秒级打到毫秒级
数据库·kingbase·金仓
雷工笔记3 小时前
Navicat Premium 17 软件安装记录
数据库
wenlonglanying3 小时前
Ubuntu 系统下安装 Nginx
数据库·nginx·ubuntu
数据库小组4 小时前
10 分钟搞定!Docker 一键部署 NineData 社区版
数据库·docker·容器·database·数据库管理工具·ninedata·迁移工具
爬山算法4 小时前
MongoDB(38)如何使用聚合进行投影?
数据库·mongodb
l1t4 小时前
Deep Seek总结的APSW 和 SQLite 的关系
数据库·sqlite
Pocker_Spades_A5 小时前
基于代价模型的连接条件下推:复杂SQL查询的性能优化实践
数据库·sql·性能优化