站内链接:

集合和文档

insert

insert()是 MongoDB 中用于向集合中插入新文档的方法。它可以一次插入单个文档或多个文档到指定的集合中。下面是insert()方法的用法说明:

1
db.collection.insert(<document>)
  • db.collection:表示要进行插入操作的集合名称。
  • <document>:表示要插入的文档或文档数组。

例如:

1
db.users.insert({ name: 'John', age: 30 });

以上示例表示向名为”users”的集合中插入一个文档,该文档包含”name”和”age”字段。 也可以一次插入多个文档:

1
2
3
4
db.users.insert([
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
]);

以上示例表示向名为”users”的集合中插入两个文档。另外,还可以使用insertOne()方法插入单个文档,使用insertMany()方法插入多个文档。这些方法提供更灵活的选项和错误处理机制。

  • insertMany: 原子操作,要么所有文档都成功插入,要么都不插入,保证了操作的原子性,其是一次性插入多个
  • insert: 逐个插入文档,每次插入都是一个单独的操作

需要注意的是,如果插入的文档中没有指定_id字段,MongoDB 会自动生成一个唯一的_id值作为文档的主键。如果指定了_id字段,则会使用该字段的值作为主键。

find

find()是 MongoDB 中用于查询文档的方法,它可以根据指定的查询条件返回符合条件的文档结果集。下面是find()方法常用的语法说明:

1
db.collection.find(<query>, <projection>)
  • db.collection:表示要进行查询的集合名称。
  • <query>:表示查询条件,使用键值对的形式指定查询条件。
  • <projection>:表示投影操作,用于指定要返回的字段或排除的字段。可以使用投影操作符来控制返回的文档结构。

例如:

1
2
3
4
// 单个query
db.users.find({ name: 'John' });
// &条件
db.users.find({ name: 'john', age: { $gt: 18 } });

常用的查询操作符:

  • 等于:{ field: value }
  • 小于:{ field: { $lt: value } }
  • 大于:{ field: { $gt: value } }
  • 小于等于:{ field: { $lte: value } }
  • 大于等于:{ field: { $gte: value } }
  • 不等于:{ field: { $ne: value } }
  • field 包含于给定列表:{ field: { $in: [value1, value2] } }
  • field 不包含于给定列表:{ field: { $nin: [value1, value2] } }
  • 逻辑与:{ $and: [ { condition1 }, { condition2 } ] }
  • 逻辑或:{ $or: [ { condition1 }, { condition2 } ] }
  • 正则表达式:{ field: /pattern/ }
  • 包含:{ field: { $all: [value1, value2] } }
  • 长度或个数: { field: { $size: 3 } }
  • 是否存在: { field: { $exists: true } }

此外,还可以在find()方法中使用其他操作符和选项,如sort()用于对结果进行排序,limit()用于限制返回结果数量,skip()用于跳过指定数量的结果等。

update

update()是 MongoDB 中用于更新文档的方法,它可以根据指定的条件更新一个或多个文档。

1
2
3
4
5
6
7
8
9
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)

参数说明:

  • <query>:指定更新的条件,使用 MongoDB 的查询语法来匹配需要更新的文档。
  • <update>:指定更新的操作,可以使用更新操作符(如$set$unset等)来修改文档的字段值。
  • upsert:可选参数,表示如果匹配的文档不存在,则是否插入新文档。默认值为false,即不进行插入操作。
  • multi:可选参数,表示是否更新多个匹配的文档。默认值为false,即只更新第一个匹配的文档。
  • writeConcern:可选参数,用于指定写入操作的安全级别和确认策略。

下面是一些常见的示例用法:

  1. 更新单个文档:
1
2
3
4
5
6
db.collection.update(
// query
{ _id: ObjectId('60ae7f11a620bc1112345678') },
// update
{ $set: { status: 'inactive' } }
);
  1. 更新多个文档,类似替换所有:
1
db.collection.update({ age: { $gte: 18 } }, { $inc: { age: 1 } }, { multi: true });
  1. 更新不存在的文档(插入新文档):
1
db.collection.update({ _id: ObjectId('60ae7f11a620bc1112345678') }, { $set: { name: 'John' } }, { upsert: true });
  1. 更新文档并设置写入安全级别:
1
2
3
4
5
db.collection.update(
{ _id: ObjectId('60ae7f11a620bc1112345678') },
{ $set: { status: 'active' } },
{ writeConcern: { w: 'majority' } }
);

delete

deleteOne()方法用于删除符合指定条件的第一个文档,而deleteMany()方法用于删除符合指定条件的所有文档。

  1. deleteOne()方法:
1
2
3
4
5
6
db.collection.deleteOne(
<filter>,
{
writeConcern: <document>
}
)

参数说明:

  • <filter>:指定删除的条件,使用 MongoDB 的查询语法来匹配要删除的文档。
  • writeConcern:可选参数,用于指定写入操作的安全级别和确认策略。

示例用法:

1
db.collection.deleteOne({ _id: ObjectId('60ae7f11a620bc1112345678') });
  1. deleteMany()方法:
1
2
3
4
5
6
db.collection.deleteMany(
<filter>,
{
writeConcern: <document>
}
)

示例用法:

1
db.collection.deleteMany({ status: 'inactive' });

需要注意的是,删除操作是不可逆的,请谨慎执行删除操作,并确保在删除文档之前做好适当的备份和确认操作。

remove

remove是 MongoDB 中用于删除文档的方法。它可以根据指定的查询条件删除满足条件的文档。

1
db.collection.remove(query, options)

参数:

  • query:删除文档的查询条件,可以是一个查询对象或查询表达式。
  • options:可选参数,用于指定额外的选项,例如排序、限制删除数量等。

假设有一个集合students,其中包含如下文档:

1
2
3
{ "_id": 1, "name": "Alice", "age": 25 }
{ "_id": 2, "name": "Bob", "age": 30 }
{ "_id": 3, "name": "Charlie", "age": 28 }

要删除age大于等于 30 的文档,可以使用以下命令:

1
db.students.remove({ age: { $gte: 30 } })

执行后,集合中的文档将变为:

1
2
{ "_id": 1, "name": "Alice", "age": 25 }
{ "_id": 3, "name": "Charlie", "age": 28 }

需要注意的是,remove方法会将满足条件的所有文档都删除,下面命令就是将集合中的所有文档删除:

1
db.collectionA.remove({});

drop

在 MongoDB 中,drop()方法用于删除指定的集合。语法如下:

1
db.collectionName.drop();

其中,collectionName为要删除的集合的名称。使用drop()方法可以完全删除集合,包括集合中的所有文档和索引。注意,删除集合后,无法恢复其中的数据,因此在执行删除操作前应谨慎考虑。 假设存在一个名为users的集合,要删除该集合,可以执行以下命令:

1
db.users.drop();

执行后,集合users将被完全删除,不再存在于数据库中。

aggregate

聚合操作用于对集合中的文档进行数据处理和计算,并返回结果集。可以通过聚合管道(Aggregation Pipeline)定义一系列的阶段(Stage),每个阶段依次处理输入的文档,并将结果传递给下一个阶段。聚合操作可以用于统计、分组、筛选、排序等复杂的数据处理需求。聚合的结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
db.collection.aggregate([
{ $stage1: { <stage1 parameters> } },
{ $stage2: { <stage2 parameters> } },
// ...
{ $stageN: { <stageN parameters> } }
])

// 原始数据,下面的操作都基于该数据
use test1
const documents = [
{
"_id": 1,
"course": "Python表达式问题求解实训",
"author": "李暾",
"tags": [
"Python基础",
"求解"
],
"learning_num": 1882
},
{
"_id": 2,
"course": "Java语言之基本语法",
"author": "余跃",
"tags": [
"Java基础",
"语法"
],
"learning_num": 814
},
{
"_id": 3,
"course": "Python面向对象编程实训",
"author": "李暾",
"tags": [
"Python基础",
"面向对象"
],
"learning_num": 143
},
{
"_id": 4,
"course": "Android综合实训之物联网移动应用开发(1)",
"author": "prophet5",
"tags": [
"Android",
"物联网",
"移动开发"
],
"learning_num": 207
}
];
db.educoder.insert(document)

下面是一些常用的聚合操作示例:

  • $match:用于筛选文档,只输出满足指定条件的文档。
1
2
3
4
// 格式:{ $match: { field: value } }

> db.educoder.aggregate({$match:{learning_num:1882}});
{ "_id" : 1, "course" : "Python表达式问题求解实训", "author" : "李暾", "tags" : [ "Python基础", "求解" ], "learning_num" : 1882 }
  • $group:用于按照指定字段对文档进行分组,并进行聚合计算。
1
2
3
4
5
6
7
8
// { $group: { _id: "$field", count: { $sum: 1 } } }

// a. 按author字段进行分组
// b. 选择每个分组中第一个出现的course字段的值
> db.educoder.aggregate([{$group:{_id:'$author', first_course:{$first:'$course'}}}]);
{ "_id" : "prophet5", "first_course" : "Android综合实训之物联网移动应用开发(1)" }
{ "_id" : "李暾", "first_course" : "Python表达式问题求解实训" }
{ "_id" : "余跃", "first_course" : "Java语言之基本语法" }
  • $project:用于投影指定的字段,控制输出的文档结构。
1
2
3
4
5
6
7
8
9
// { $project: { field1: 1, field2: 1, ... } }


// 0-表示隐藏,1-表示输出
> db.educoder.aggregate({$project:{_id:0,course:1,learning_num:1}});
{ "course" : "Python表达式问题求解实训", "learning_num" : 1882 }
{ "course" : "Java语言之基本语法", "learning_num" : 814 }
{ "course" : "Python面向对象编程实训", "learning_num" : 143 }
{ "course" : "Android综合实训之物联网移动应用开发(1)", "learning_num" : 207 }
  • $sort:用于对文档进行排序。
1
2
3
4
5
6
7
8
// { $sort: { field: 1 } }

// 根据learning_number逆序
> db.educoder.aggregate({$sort:{learning_num:1}});
{ "_id" : 3, "course" : "Python面向对象编程实训", "author" : "李暾", "tags" : [ "Python基础", "面向对象" ], "learning_num" : 143 }
{ "_id" : 4, "course" : "Android综合实训之物联网移动应用开发(1)", "author" : "prophet5", "tags" : [ "Android", "物联网", "移动开发" ], "learning_num" : 207 }
{ "_id" : 2, "course" : "Java语言之基本语法", "author" : "余跃", "tags" : [ "Java基础", "语法" ], "learning_num" : 814 }
{ "_id" : 1, "course" : "Python表达式问题求解实训", "author" : "李暾", "tags" : [ "Python基础", "求解" ], "learning_num" : 1882 }
  • $limit:用于限制输出的文档数量。
1
2
3
4
5
6
// { $limit: 10 }

> db.educoder.aggregate({$limit:3});
{ "_id" : 1, "course" : "Python表达式问题求解实训", "author" : "李暾", "tags" : [ "Python基础", "求解" ], "learning_num" : 1882 }
{ "_id" : 2, "course" : "Java语言之基本语法", "author" : "余跃", "tags" : [ "Java基础", "语法" ], "learning_num" : 814 }
{ "_id" : 3, "course" : "Python面向对象编程实训", "author" : "李暾", "tags" : [ "Python基础", "面向对象" ], "learning_num" : 143 }
  • $skip:用于跳过指定数量的文档。
1
2
3
4
5
// { $skip: 10 }

> db.educoder.aggregate([{$skip:2}]);
{ "_id" : 3, "course" : "Python面向对象编程实训", "author" : "李暾", "tags" : [ "Python基础", "面向对象" ], "learning_num" : 143 }
{ "_id" : 4, "course" : "Android综合实训之物联网移动应用开发(1)", "author" : "prophet5", "tags" : [ "Android", "物联网", "移动开发" ], "learning_num" : 207 }

以下是一个简单的聚合操作示例,假设存在一个名为orders的集合,其中包含订单信息,我们要统计每个客户的订单数量:

1
2
3
4
db.orders.aggregate([
// $group表示:按照customer字段分组,并使用$sum操作符计算每个分组中的文档数量,将结果存储在totalOrders字段中。
{ $group: { _id: '$customer', totalOrders: { $sum: 1 } } },
]);

分页

在 MongoDB 中,分页操作可以使用limitskip两个方法来实现。

  • limit方法用于限制返回结果的文档数量,它接受一个整数参数,表示要返回的文档数量。例如,要获取前 10 个文档,可以使用limit(10)

  • skip方法用于跳过指定数量的文档,它接受一个整数参数,表示要跳过的文档数量。例如,要从第 11 个文档开始获取结果,可以使用skip(10)

分页操作通常与排序操作结合使用,以确保结果按照指定的顺序进行分页。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 假设有一个名为"users"的集合,包含大量用户文档

// 每页显示的文档数量
const pageSize = 10;

// 当前页数(从1开始)
const currentPage = 2;

// 计算要跳过的文档数量
const skipCount = (currentPage - 1) * pageSize;

// 查询并分页获取结果
const result = db.users.find().skip(skipCount).limit(pageSize);

// 输出结果
result.forEach((doc) => {
printjson(doc);
});

在上述示例中,我们设置了每页显示 10 个文档,并指定当前页为第 2 页。通过计算要跳过的文档数量,然后使用skip方法跳过相应数量的文档,再使用limit方法限制返回的文档数量,从而实现了分页操作。

需要注意的是,使用skip方法可能会影响查询性能,特别是在处理大量文档时。在实际应用中,建议使用基于游标(cursor)的分页方法,如使用find方法的limitskip选项结合使用,或者使用aggregate方法进行更复杂的分页和排序操作。

rename

renameCollection 是 MongoDB 中用于重命名集合的方法。它允许您将一个集合重命名为另一个名称,而无需复制或移动文档。

1
db.collection.renameCollection("newCollectionName");

其中,collection 是要重命名的集合的名称,而 "newCollectionName" 是要为集合设置的新名称。

请注意,renameCollection 方法在同一个数据库中执行重命名操作,因此不涉及跨数据库的移动或复制。重命名后,集合的所有索引、选项和文档将保持不变。

runCommand

db.runCommand 是 MongoDB shell 中用于执行数据库命令的方法。它允许你以命令对象的形式执行各种数据库操作,例如查询、更新、删除等。常见的是利用该命令进行地理空间查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1. 基本操作
// 执行一个简单的查询命令
const result = db.runCommand({ find: 'collectionName', filter: { field: 'value' } });
// 执行一个更新命令
const result = db.runCommand({
update: 'collectionName',
updates: [{ q: { field: 'value' }, u: { $set: { field: 'newValue' } } }],
});
// 执行一个删除命令
const result = db.runCommand({ delete: 'collectionName', deletes: [{ q: { field: 'value' }, limit: 1 }] });

// 2. 地理空间
db.runCommand({
geoNear: 'people', // 要进行地理空间查询的集合名称
near: { type: 'Point', coordinates: [116.403981, 39.914935] }, // 给定的坐标点
spherical: true, // 表示使用球面几何计算距离
minDistance: 100, // 最小距离,单位为米
maxDistance: 3000, // 最大距离,单位为米
});

数据库

数据库

  1. 更改数据库名

renameDatabase在新版本已经被废弃了,更改数据库名称的推荐做法是创建一个新的数据库,将原始数据库中的数据复制到新的数据库中,然后删除原始数据库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// a. 创建新数据库
use old_db

// b. 将collection移动到新数据库,其中
var myCollections = db.getCollectionNames()
myCollections.forEach(function(ele) {
var documents = db.getCollection(ele).find()
if (!documents.hasNext()) {
// db.getSiblingDB('bamboo')表示获取某个数据库的句柄
db.getSiblingDB('bamboo').createCollection(ele);
return
}
documents.forEach(function(doc) {
db.getSiblingDB('bamboo').getCollection(ele).insert(doc);
})
})

// c. 删除老数据库
db.getSiblingDB('old_db').dropDatabase()
  1. 删除数据库

dropDatabase()删除

索引

  1. 定义

在 MongoDB 中,索引是用于提高查询性能的重要机制。MongoDB 支持多种类型的索引,包括以下几种常见的索引类型:

  • 单字段索引(Single-field Indexes):对单个字段创建的索引,可以通过指定字段名称创建。最常用的索引类型是 B-Tree 索引,它支持快速的等值查询和范围查询。
  • 复合索引(Compound Indexes):由多个字段组成的索引,可以通过指定多个字段名称创建。复合索引可以支持多个字段的查询条件,提高多字段条件查询的性能。
  • 多键索引(Multikey Indexes):适用于数组或嵌套文档字段,可以对数组中的每个元素或嵌套文档中的字段创建索引。多键索引可以加快对数组中的元素进行匹配和筛选的查询。
  • 文本索引(Text Indexes):用于全文搜索和文本匹配,适用于对文本字段进行模糊匹配和关键词搜索。文本索引使用全文搜索算法,支持文本相关的查询和排序。
  • 地理空间索引(Geospatial Indexes):适用于存储地理位置数据的字段,支持对地理空间数据进行查询和分析,如查询指定范围内的位置数据、计算距离等。
  • 散列索引(Hashed Indexes):使用哈希算法对字段值进行散列后创建的索引。散列索引适用于等值查询,可以提供均匀分布的索引值。

创建索引的语法示例:

1
2
3
4
5
6
7
8
9
10
11
// 创建单字段索引
db.collection.createIndex({ field: 1 });

// 创建复合索引
db.collection.createIndex({ field1: 1, field2: -1 });

// 创建文本索引
db.collection.createIndex({ text: 'text' });

// 创建地理空间索引
db.collection.createIndex({ location: '2dsphere' });

除了以上的索引类型,MongoDB 还支持更高级的索引功能,如部分索引、稀疏索引、TTL 索引等,以满足不同的数据查询需求。

使用适当的索引可以大幅提高查询性能和响应时间,但索引的选择和创建需要根据具体的业务需求和数据访问模式进行权衡和优化。同时,索引的维护也需要考虑存储空间和写入性能的影响。

  1. 获取当前集合的所有索引信息: db.Col1.getIndexes()
  2. 测试

常见索引的创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use test2
document = [
{
"_id" : "1",
"title" : "提升程序员工作效率的6个工具利器",
"tags" : "Alfred,幕布",
"follwers" : 543
},
{
"_id" : "2",
"title" : "我是如何从零开始学习前端的",
"tags" : "HTML,Html5,CSS",
"follwers" : 1570
},
{
"_id" : "3",
"title" : "20个非常有用的JAVA程序片段",
"tags" : "Java,编程",
"follwers" : 1920
}
]
db.article.insert(document)

// 用字段 follwers 和 title 创建复合升序索引;
db.article.createIndex({ follwers: 1, title: 1 });

// 用字段 tags 创建多 key 降序索引;
db.article.createIndex({ tags: -1 });

// 用_id创建哈希索引;
db.article.createIndex({ _id: "hashed" });

// 用字段 title 和 tags 创建文本索引。
db.article.createIndex({
title:"text",
tags:"text"
})