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 } }
    ]
})
相关推荐
BestandW1shEs2 小时前
谈谈Mysql的常见基础问题
数据库·mysql
重生之Java开发工程师2 小时前
MySQL中的CAST类型转换函数
数据库·sql·mysql
教练、我想打篮球2 小时前
66 mysql 的 表自增长锁
数据库·mysql
Ljw...2 小时前
表的操作(MySQL)
数据库·mysql·表的操作
哥谭居民00012 小时前
MySQL的权限管理机制--授权表
数据库
wqq_9922502772 小时前
ssm旅游推荐系统的设计与开发
数据库·旅游
难以触及的高度3 小时前
mysql中between and怎么用
数据库·mysql
Jacky(易小天)3 小时前
MongoDB比较查询操作符中英对照表及实例详解
数据库·mongodb·typescript·比较操作符
Karoku0664 小时前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch