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

MongoDB基础增删改查操作入门

2022-04-111.6k 阅读

一、MongoDB 基础概念

1.1 文档(Document)

MongoDB 中的数据以文档形式存储,文档是一个键值对(key - value pairs)的集合,在 JSON 格式中非常常见。例如,一个简单的用户文档可以如下表示:

{
    "name": "John Doe",
    "age": 30,
    "email": "johndoe@example.com"
}

这里,nameageemail 是键,而 "John Doe"30"johndoe@example.com" 是对应的值。文档可以嵌套,意味着一个文档的值可以是另一个文档或者一个文档数组。例如:

{
    "name": "Jane Smith",
    "age": 25,
    "email": "janesmith@example.com",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
    },
    "phoneNumbers": [
        {
            "type": "home",
            "number": "555 - 123 - 4567"
        },
        {
            "type": "work",
            "number": "555 - 987 - 6543"
        }
    ]
}

这种灵活性使得 MongoDB 能轻松适应各种数据结构,而不需要像关系型数据库那样预先定义表结构。

1.2 集合(Collection)

集合是一组文档的容器,类似于关系型数据库中的表。但与表不同的是,集合不需要预先定义结构,集合中的文档可以有不同的字段和结构。例如,一个 users 集合可以包含上述用户文档,同时也可以包含具有不同字段的其他用户文档:

// 第一个用户文档
{
    "name": "Alice",
    "age": 28,
    "email": "alice@example.com"
}
// 第二个用户文档,具有不同的结构
{
    "username": "bob123",
    "password": "hashed_password",
    "isAdmin": true
}

这种灵活性使得 MongoDB 在处理数据时更加敏捷,适合快速迭代的开发场景。

1.3 数据库(Database)

数据库是一个或多个集合的容器。一个 MongoDB 实例可以包含多个数据库,每个数据库都有自己独立的权限控制和存储空间。例如,一个应用程序可能有一个用于存储用户数据的 users_db,另一个用于存储订单数据的 orders_db。在 MongoDB 中,数据库名称不区分大小写,但为了遵循惯例和避免混淆,通常使用小写字母。

二、插入操作(Insertion)

2.1 插入单个文档

在 MongoDB 中,使用 insertOne 方法插入单个文档。假设我们有一个 students 集合,要插入一个学生的信息,代码如下:

const { MongoClient } = require('mongodb');

// 连接 MongoDB 实例
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function insertStudent() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const student = {
            name: "Tom",
            age: 18,
            grade: "12th"
        };

        const result = await students.insertOne(student);
        console.log(`Inserted document with _id: ${result.insertedId}`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

insertStudent();

在上述代码中:

  1. 首先通过 MongoClient 连接到本地的 MongoDB 实例(地址为 mongodb://localhost:27017)。
  2. 选择 school 数据库和 students 集合。
  3. 创建一个 student 文档。
  4. 使用 insertOne 方法将文档插入到 students 集合中。insertOne 方法返回一个结果对象,其中 insertedId 是插入文档的唯一标识符。

2.2 插入多个文档

使用 insertMany 方法可以一次性插入多个文档。假设我们要插入多个学生的信息,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function insertManyStudents() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const studentsToInsert = [
            {
                name: "Alice",
                age: 17,
                grade: "11th"
            },
            {
                name: "Bob",
                age: 19,
                grade: "12th"
            }
        ];

        const result = await students.insertMany(studentsToInsert);
        console.log(`Inserted ${result.insertedCount} documents`);
        console.log(`Inserted document IDs: ${result.insertedIds}`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

insertManyStudents();

在这段代码中:

  1. 同样连接到 MongoDB 实例并选择 school 数据库和 students 集合。
  2. 创建一个包含多个学生文档的数组 studentsToInsert
  3. 使用 insertMany 方法插入这些文档。insertMany 方法返回的结果对象中,insertedCount 表示插入的文档数量,insertedIds 是一个包含所有插入文档唯一标识符的对象。

三、查询操作(Querying)

3.1 基本查询

查询是从集合中检索文档的操作。使用 find 方法进行基本查询。例如,要从 students 集合中查询所有学生的信息,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function findAllStudents() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const cursor = students.find({});
        const studentsList = await cursor.toArray();
        console.log(studentsList);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findAllStudents();

在上述代码中:

  1. 连接到 MongoDB 实例并选择 school 数据库和 students 集合。
  2. 使用 find({}) 方法查询集合中的所有文档。find 方法返回一个游标(cursor)对象,游标是一个指向查询结果集的指针。
  3. 使用 cursor.toArray() 方法将游标中的所有文档转换为数组并打印出来。

3.2 条件查询

可以在 find 方法中传入查询条件来筛选文档。例如,要查询年龄大于 18 岁的学生,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function findStudentsAbove18() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const query = { age: { $gt: 18 } };
        const cursor = students.find(query);
        const studentsList = await cursor.toArray();
        console.log(studentsList);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsAbove18();

在这段代码中:

  1. 定义了一个查询条件 { age: { $gt: 18 } },其中 $gt 是 MongoDB 的比较操作符,表示“大于”。
  2. 将查询条件传入 find 方法,只有满足条件的文档才会被返回。

3.3 投影(Projection)

投影用于指定返回文档中的字段。例如,要查询学生的姓名和年级,而不返回年龄,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function findStudentsWithProjection() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const query = {};
        const projection = { name: 1, grade: 1, _id: 0 };
        const cursor = students.find(query, projection);
        const studentsList = await cursor.toArray();
        console.log(studentsList);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsWithProjection();

在上述代码中:

  1. projection 对象中,将 namegrade 字段设置为 1,表示要返回这些字段;将 _id 字段设置为 0,表示不返回 _id 字段。默认情况下,_id 字段会被返回。

四、更新操作(Updating)

4.1 更新单个文档

使用 updateOne 方法更新单个文档。例如,要将名为 Tom 的学生的年级更新为 13th,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function updateStudentGrade() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const filter = { name: "Tom" };
        const update = { $set: { grade: "13th" } };

        const result = await students.updateOne(filter, update);
        console.log(`${result.matchedCount} document(s) matched the filter criteria`);
        console.log(`${result.modifiedCount} document(s) were updated`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

updateStudentGrade();

在这段代码中:

  1. 定义了一个筛选条件 filter,用于找到名为 Tom 的学生文档。
  2. 定义了一个更新操作 update,使用 $set 操作符将 grade 字段更新为 13th
  3. updateOne 方法返回的结果对象中,matchedCount 表示匹配筛选条件的文档数量,modifiedCount 表示实际更新的文档数量。

4.2 更新多个文档

使用 updateMany 方法可以更新多个文档。例如,要将所有年龄为 18 岁的学生的年级都增加一级,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function updateStudentsGrade() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const filter = { age: 18 };
        const update = { $inc: { grade: 1 } };

        const result = await students.updateMany(filter, update);
        console.log(`${result.matchedCount} document(s) matched the filter criteria`);
        console.log(`${result.modifiedCount} document(s) were updated`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

updateStudentsGrade();

在上述代码中:

  1. 筛选条件 filter 找到所有年龄为 18 岁的学生文档。
  2. 更新操作 update 使用 $inc 操作符将 grade 字段的值增加 1。
  3. updateMany 方法返回的结果对象同样包含 matchedCountmodifiedCount 字段,用于表示匹配和更新的文档数量。

五、删除操作(Deletion)

5.1 删除单个文档

使用 deleteOne 方法删除单个文档。例如,要删除名为 Alice 的学生文档,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function deleteStudent() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const filter = { name: "Alice" };

        const result = await students.deleteOne(filter);
        console.log(`${result.deletedCount} document(s) were deleted`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

deleteStudent();

在这段代码中:

  1. 定义了筛选条件 filter,用于找到名为 Alice 的学生文档。
  2. 使用 deleteOne 方法删除匹配的文档,deleteOne 方法返回的结果对象中的 deletedCount 字段表示删除的文档数量。

5.2 删除多个文档

使用 deleteMany 方法删除多个文档。例如,要删除所有年龄小于 18 岁的学生文档,代码如下:

const { MongoClient } = require('mongodb');

const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function deleteStudents() {
    try {
        await client.connect();
        const database = client.db('school');
        const students = database.collection('students');

        const filter = { age: { $lt: 18 } };

        const result = await students.deleteMany(filter);
        console.log(`${result.deletedCount} document(s) were deleted`);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

deleteStudents();

在上述代码中:

  1. 筛选条件 filter 使用 $lt 操作符找到所有年龄小于 18 岁的学生文档。
  2. deleteMany 方法删除所有匹配的文档,返回结果中的 deletedCount 字段表示删除的文档总数。

通过上述对 MongoDB 基础增删改查操作的介绍,希望能帮助你快速入门 MongoDB 的数据操作,为进一步深入学习和实际应用打下坚实基础。在实际开发中,需要根据具体业务需求灵活运用这些操作,以实现高效的数据管理和处理。同时,MongoDB 还提供了许多高级功能,如聚合、索引等,后续可以进一步探索学习。