MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

MongoDB Shell客户端的交互式操作详解

2021-08-047.8k 阅读

连接到 MongoDB Shell

MongoDB Shell 是与 MongoDB 数据库进行交互的主要工具。要启动 MongoDB Shell,首先确保 MongoDB 服务正在运行。在命令行中,导航到 MongoDB 的 bin 目录(如果 MongoDB 已添加到系统路径中,则无需导航),然后执行以下命令:

mongo

上述命令将使用默认设置连接到本地运行的 MongoDB 实例,默认端口是 27017。如果 MongoDB 运行在不同的主机或端口上,可以使用以下命令进行连接:

mongo <host>:<port>

例如,如果 MongoDB 运行在 192.168.1.100 主机的 27018 端口上,连接命令为:

mongo 192.168.1.100:27018

数据库操作

查看当前数据库

在 MongoDB Shell 中,可以使用 db 命令查看当前连接的数据库。例如:

db

首次连接时,默认的数据库是 test

切换数据库

使用 use 命令可以切换到指定的数据库。如果指定的数据库不存在,MongoDB 会在首次插入数据时创建它。例如,要切换到名为 myDB 的数据库,可以执行以下命令:

use myDB

查看所有数据库

使用 show dbs 命令可以查看 MongoDB 服务器上所有的数据库列表。例如:

show dbs

该命令会列出所有数据库及其占用的空间大小。

删除数据库

要删除当前连接的数据库,可以使用 db.dropDatabase() 方法。例如,确保当前连接到要删除的数据库,然后执行:

db.dropDatabase()

集合操作

创建集合

在 MongoDB 中,集合类似于关系型数据库中的表。要创建一个集合,可以使用 db.createCollection() 方法。例如,要在当前数据库中创建一个名为 myCollection 的集合,可以执行以下命令:

db.createCollection("myCollection")

集合创建时还可以指定一些选项,例如设置集合的 capped 属性,创建固定集合。固定集合是一种特殊的集合,它有固定的大小,当达到这个大小后,新插入的数据会覆盖旧的数据。以下是创建一个固定集合的示例:

db.createCollection("myCappedCollection", { capped : true, size : 100000, max : 1000 } )

上述命令创建了一个名为 myCappedCollection 的固定集合,大小为 100000 字节,最多可容纳 1000 个文档。

查看集合

使用 show collections 命令可以查看当前数据库中的所有集合。例如:

show collections

删除集合

要删除当前数据库中的一个集合,可以使用 db.<collection_name>.drop() 方法。例如,要删除名为 myCollection 的集合,可以执行:

db.myCollection.drop()

文档操作

插入文档

在 MongoDB 中,文档是存储在集合中的基本数据单元,类似于关系型数据库中的行。要向集合中插入一个文档,可以使用 insertOne() 方法。例如,向 myCollection 集合中插入一个简单的文档:

db.myCollection.insertOne( { name: "John", age: 30 } )

上述命令插入了一个包含 nameage 字段的文档。insertOne() 方法会返回一个包含插入结果的对象,其中包含插入的文档的 _id 字段。如果要插入多个文档,可以使用 insertMany() 方法。例如:

db.myCollection.insertMany([
    { name: "Jane", age: 25 },
    { name: "Bob", age: 35 }
])

insertMany() 方法返回的对象包含插入的文档的 _id 数组。

查询文档

MongoDB 提供了强大的查询功能。使用 find() 方法可以查询集合中的文档。要查询 myCollection 集合中的所有文档,可以执行:

db.myCollection.find()

上述命令会返回集合中的所有文档。通常,我们会使用查询条件来筛选特定的文档。例如,要查询 age 大于 30 的文档,可以使用以下命令:

db.myCollection.find( { age: { $gt: 30 } } )

这里的 $gt 是 MongoDB 的比较操作符,表示“大于”。其他常用的比较操作符还有 $lt(小于)、$gte(大于等于)、$lte(小于等于)、$eq(等于)、$ne(不等于)等。

要查询包含特定字段的文档,可以直接在查询条件中指定字段名。例如,要查询 nameJohn 的文档:

db.myCollection.find( { name: "John" } )

更新文档

使用 updateOne() 方法可以更新集合中的单个文档。例如,要将 myCollection 集合中 nameJohn 的文档的 age 字段更新为 31,可以执行:

db.myCollection.updateOne(
    { name: "John" },
    { $set: { age: 31 } }
)

这里的 $set 操作符用于指定要更新的字段及其新值。如果要更新多个文档,可以使用 updateMany() 方法。例如,要将 age 大于 30 的所有文档的 age 字段加 1,可以执行:

db.myCollection.updateMany(
    { age: { $gt: 30 } },
    { $inc: { age: 1 } }
)

$inc 操作符用于对字段的值进行递增操作。

删除文档

使用 deleteOne() 方法可以删除集合中的单个文档。例如,要删除 myCollection 集合中 nameJohn 的文档,可以执行:

db.myCollection.deleteOne( { name: "John" } )

如果要删除多个文档,可以使用 deleteMany() 方法。例如,要删除 age 大于 35 的所有文档,可以执行:

db.myCollection.deleteMany( { age: { $gt: 35 } } )

索引操作

创建索引

索引可以显著提高查询性能。在 MongoDB 中,可以使用 createIndex() 方法为集合创建索引。例如,要为 myCollection 集合的 name 字段创建一个单字段索引,可以执行:

db.myCollection.createIndex( { name: 1 } )

这里的 1 表示升序索引,如果使用 -1 则表示降序索引。要创建复合索引,即基于多个字段的索引,可以将多个字段及其排序顺序作为参数传递。例如,创建一个基于 nameage 字段的复合索引:

db.myCollection.createIndex( { name: 1, age: -1 } )

查看索引

使用 getIndexes() 方法可以查看集合的所有索引。例如:

db.myCollection.getIndexes()

该命令会返回一个包含集合所有索引信息的数组,包括索引名称、字段和其他相关信息。

删除索引

要删除集合中的一个索引,可以使用 dropIndex() 方法。例如,要删除名为 name_1 的索引(索引名称通常由字段名和排序顺序组成),可以执行:

db.myCollection.dropIndex( { name: 1 } )

也可以通过索引名称来删除索引,例如:

db.myCollection.dropIndex("name_1")

要删除集合中的所有索引,可以使用 dropIndexes() 方法:

db.myCollection.dropIndexes()

聚合操作

聚合操作允许对数据进行复杂的处理和分析。MongoDB 提供了 aggregate() 方法来执行聚合操作。聚合管道由多个阶段组成,每个阶段对数据进行特定的转换。

例如,要计算 myCollection 集合中所有文档的 age 字段的平均值,可以使用以下聚合管道:

db.myCollection.aggregate([
    { $group: { _id: null, averageAge: { $avg: "$age" } } }
])

这里的 $group 阶段根据 _id 字段对文档进行分组,_id: null 表示将所有文档分为一组。$avg 是一个聚合操作符,用于计算 age 字段的平均值。

另一个常见的聚合操作是 $match 阶段,用于筛选文档。例如,要先筛选出 age 大于 30 的文档,然后计算这些文档的平均年龄:

db.myCollection.aggregate([
    { $match: { age: { $gt: 30 } } },
    { $group: { _id: null, averageAge: { $avg: "$age" } } }
])

$sort 阶段可用于对聚合结果进行排序。例如,要按 age 字段降序对文档进行排序,然后取前 10 个文档:

db.myCollection.aggregate([
    { $sort: { age: -1 } },
    { $limit: 10 }
])

游标操作

当执行查询时,find() 方法返回一个游标对象。游标是一个指向查询结果集的指针,允许逐个访问结果集中的文档。

默认情况下,MongoDB Shell 会自动迭代游标并显示前 20 个文档。如果结果集较大,可以使用 it 命令迭代显示更多文档。例如:

var cursor = db.myCollection.find()
cursor.it()

也可以使用 forEach() 方法对游标中的每个文档执行自定义操作。例如,要打印 myCollection 集合中每个文档的 name 字段:

db.myCollection.find().forEach( function(doc) {
    print(doc.name)
} )

游标还支持一些其他方法,如 count() 方法用于获取结果集中文档的数量:

var count = db.myCollection.find().count()
print(count)

管理用户和权限

创建用户

在 MongoDB 中,可以使用 db.createUser() 方法创建用户。例如,要在 admin 数据库中创建一个具有管理员权限的用户,可以执行以下命令:

use admin
db.createUser(
    {
        user: "adminUser",
        pwd: "password123",
        roles: [ { role: "root", db: "admin" } ]
    }
)

上述命令创建了一个名为 adminUser 的用户,密码为 password123,并赋予其 root 角色,该角色具有最高权限。

要在普通数据库中创建用户并赋予特定权限,可以在相应数据库中执行 createUser() 方法。例如,在 myDB 数据库中创建一个具有读写权限的用户:

use myDB
db.createUser(
    {
        user: "myUser",
        pwd: "userPassword",
        roles: [ { role: "readWrite", db: "myDB" } ]
    }
)

查看用户

使用 show users 命令可以查看当前数据库中的所有用户。例如:

use myDB
show users

修改用户密码

要修改用户的密码,可以使用 db.changeUserPassword() 方法。例如,要修改 myUser 用户的密码:

use myDB
db.changeUserPassword("myUser", "newPassword")

删除用户

使用 db.dropUser() 方法可以删除用户。例如,要删除 myUser 用户:

use myDB
db.dropUser("myUser")

备份与恢复

备份数据库

MongoDB 提供了 mongodump 工具来备份数据库。在命令行中,执行以下命令可以备份整个 MongoDB 实例:

mongodump --uri="mongodb://adminUser:password123@192.168.1.100:27017/admin"

上述命令使用指定的用户名、密码和连接字符串备份 admin 数据库。如果要备份单个数据库,可以指定数据库名称:

mongodump --uri="mongodb://adminUser:password123@192.168.1.100:27017/" --db myDB

要备份特定的集合,可以使用 --collection 选项:

mongodump --uri="mongodb://adminUser:password123@192.168.1.100:27017/" --db myDB --collection myCollection

恢复数据库

使用 mongorestore 工具可以恢复备份的数据。例如,要恢复之前备份的 myDB 数据库,可以执行以下命令:

mongorestore --uri="mongodb://adminUser:password123@192.168.1.100:27017/" --dir <backup_directory>/myDB

<backup_directory>mongodump 备份数据的目录。如果要恢复特定的集合,可以指定集合名称:

mongorestore --uri="mongodb://adminUser:password123@192.168.1.100:27017/" --db myDB --collection myCollection <backup_directory>/myDB/myCollection.bson

高级查询技巧

使用正则表达式查询

MongoDB 支持使用正则表达式进行查询。例如,要查询 name 字段以 J 开头的文档,可以执行:

db.myCollection.find( { name: /^J/ } )

上述正则表达式 /^J/ 表示匹配以 J 开头的字符串。

数组查询

如果文档中包含数组字段,MongoDB 提供了多种方式进行查询。例如,假设有一个文档结构如下:

{
    name: "John",
    hobbies: [ "reading", "swimming", "coding" ]
}

要查询 hobbies 数组中包含 swimming 的文档,可以执行:

db.myCollection.find( { hobbies: "swimming" } )

如果要查询 hobbies 数组中包含多个特定元素的文档,可以使用 $all 操作符。例如,要查询 hobbies 数组中同时包含 readingcoding 的文档:

db.myCollection.find( { hobbies: { $all: [ "reading", "coding" ] } } )

嵌套文档查询

对于包含嵌套文档的结构,例如:

{
    name: "John",
    address: {
        city: "New York",
        state: "NY"
    }
}

要查询 address.cityNew York 的文档,可以使用点表示法:

db.myCollection.find( { "address.city": "New York" } )

事务操作

MongoDB 从 4.0 版本开始支持多文档事务。要使用事务,首先需要确保 MongoDB 部署为副本集。

在 MongoDB Shell 中,可以使用 startSession() 方法开始一个会话,然后在会话中启动事务。例如:

var session = db.getMongo().startSession()
session.startTransaction()
try {
    db.collection1.insertOne( { data: "data1" }, { session: session } )
    db.collection2.insertOne( { data: "data2" }, { session: session } )
    session.commitTransaction()
} catch (e) {
    session.abortTransaction()
    print(e)
} finally {
    session.endSession()
}

上述代码在一个事务中向 collection1collection2 两个集合中插入文档。如果任何一个插入操作失败,事务将回滚,不会对数据库进行任何更改。

性能优化

索引优化

确保对经常用于查询条件的字段创建索引。定期使用 db.collection.getIndexes() 查看索引使用情况,删除不必要的索引,因为索引会占用额外的存储空间并影响写操作性能。

查询优化

避免全表扫描,尽量使用索引。在查询时,合理使用查询条件和操作符,确保查询语句的高效性。例如,使用 $in 操作符时要注意其性能影响,如果数据量过大,可能需要考虑其他方式。

批量操作

在进行插入、更新或删除操作时,尽量使用批量操作方法(如 insertMany()updateMany()deleteMany()),这样可以减少客户端与服务器之间的通信次数,提高操作效率。

与编程语言集成

MongoDB 支持多种编程语言的驱动程序,如 Node.js、Python、Java 等。以 Node.js 为例,首先需要安装 mongodb 包:

npm install mongodb

然后可以在 Node.js 代码中连接到 MongoDB 并进行操作。例如:

const { MongoClient } = require('mongodb');
const uri = "mongodb://adminUser:password123@192.168.1.100:27017/?authSource=admin";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

async function run() {
    try {
        await client.connect();
        const database = client.db('myDB');
        const collection = database.collection('myCollection');

        // 插入文档
        await collection.insertOne({ name: "Node.js User", age: 28 });

        // 查询文档
        const result = await collection.find({ age: { $gt: 25 } }).toArray();
        console.log(result);
    } finally {
        await client.close();
    }
}
run().catch(console.dir);

上述代码展示了如何在 Node.js 中连接到 MongoDB,插入文档并进行查询。不同编程语言的驱动程序使用方式略有不同,但基本原理相似。通过与编程语言集成,可以将 MongoDB 无缝融入到各种应用程序开发中。

通过以上对 MongoDB Shell 客户端交互式操作的详细讲解,你应该能够熟练掌握 MongoDB 的基本操作、高级查询、索引管理、事务处理等重要功能,为开发基于 MongoDB 的应用程序奠定坚实的基础。在实际应用中,还需要根据具体的业务需求和数据特点,灵活运用这些知识,以实现高效、可靠的数据管理和应用开发。