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

MongoDB查询文档的基本操作与示例

2024-03-197.8k 阅读

MongoDB查询文档的基本操作与示例

1. 简单查询

在MongoDB中,最简单的查询就是查找集合中的所有文档。使用find()方法,不传递任何参数时,它会返回集合中的所有文档。例如,假设有一个名为students的集合,存储了学生的信息,以下是查询所有学生信息的代码示例:

// 使用JavaScript示例,连接到MongoDB数据库
const { MongoClient } = require('mongodb');
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);

async function findAllStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const allStudents = await studentsCollection.find({}).toArray();
        console.log(allStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findAllStudents();

在上述代码中,我们使用Node.js的MongoDB驱动程序,连接到本地的MongoDB实例,选择school数据库中的students集合,通过find({})方法获取所有文档,并使用toArray()方法将游标转换为数组以便于查看。

2. 条件查询

2.1 等于条件查询

通常我们不会查询所有文档,而是根据特定条件进行筛选。要查询符合某个字段等于特定值的文档,可以在find()方法的第一个参数中指定条件。例如,查询所有年龄为20岁的学生:

async function findStudentsByAge() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const studentsWithAge20 = await studentsCollection.find({ age: 20 }).toArray();
        console.log(studentsWithAge20);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsByAge();

在这个例子中,{ age: 20 }就是查询条件,表示只返回age字段值为20的文档。

2.2 比较条件查询

MongoDB提供了丰富的比较操作符,如大于($gt)、小于($lt)、大于等于($gte)、小于等于($lte)等。例如,查询所有年龄大于20岁的学生:

async function findStudentsOlderThan20() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const olderStudents = await studentsCollection.find({ age: { $gt: 20 } }).toArray();
        console.log(olderStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsOlderThan20();

这里使用了$gt操作符,{ age: { $gt: 20 } }表示age字段值大于20的文档。

2.3 不等于条件查询

使用$ne操作符可以查询字段值不等于某个值的文档。例如,查询所有年龄不等于20岁的学生:

async function findStudentsNot20() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const not20Students = await studentsCollection.find({ age: { $ne: 20 } }).toArray();
        console.log(not20Students);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsNot20();

3. 逻辑查询

3.1 与($and)查询

$and操作符用于连接多个条件,只有当所有条件都满足时,文档才会被返回。假设要查询年龄大于20岁且成绩大于80分的学生:

async function findQualifiedStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const qualifiedStudents = await studentsCollection.find({
            $and: [
                { age: { $gt: 20 } },
                { score: { $gt: 80 } }
            ]
        }).toArray();
        console.log(qualifiedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findQualifiedStudents();

在上述代码中,$and数组中包含两个条件,只有同时满足这两个条件的文档才会被返回。

3.2 或($or)查询

$or操作符只要其中一个条件满足,文档就会被返回。例如,查询年龄小于18岁或者成绩小于60分的学生:

async function findProblemStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const problemStudents = await studentsCollection.find({
            $or: [
                { age: { $lt: 18 } },
                { score: { $lt: 60 } }
            ]
        }).toArray();
        console.log(problemStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findProblemStudents();

3.3 与或混合查询

也可以进行与或混合的复杂查询。例如,查询年龄大于20岁且(成绩大于80分或者性别为男)的学生:

async function findSpecialStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const specialStudents = await studentsCollection.find({
            age: { $gt: 20 },
            $or: [
                { score: { $gt: 80 } },
                { gender: '男' }
            ]
        }).toArray();
        console.log(specialStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findSpecialStudents();

4. 范围查询

$in操作符用于查询字段值在指定数组范围内的文档,$nin则相反,查询字段值不在指定数组范围内的文档。

4.1 $in查询

例如,查询年龄为18、20、22岁的学生:

async function findStudentsByAges() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const selectedStudents = await studentsCollection.find({ age: { $in: [18, 20, 22] } }).toArray();
        console.log(selectedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsByAges();

4.2 $nin查询

查询年龄不在18、20、22岁范围内的学生:

async function findStudentsNotInAges() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const otherStudents = await studentsCollection.find({ age: { $nin: [18, 20, 22] } }).toArray();
        console.log(otherStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsNotInAges();

5. 正则表达式查询

MongoDB支持使用正则表达式进行字符串匹配查询。例如,查询名字以“张”开头的学生:

async function findZhangStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const zhangStudents = await studentsCollection.find({ name: /^张/ }).toArray();
        console.log(zhangStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findZhangStudents();

在上述代码中,/^张/是一个正则表达式,表示以“张”开头的字符串。

6. 查询字段投影

在查询时,我们可以指定返回的字段,而不是返回整个文档,这就是字段投影。例如,只查询学生的姓名和年龄,不返回其他字段:

async function findNameAndAge() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const nameAndAge = await studentsCollection.find({}, { name: 1, age: 1, _id: 0 }).toArray();
        console.log(nameAndAge);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findNameAndAge();

find()方法的第二个参数中,name: 1age: 1表示返回这两个字段,_id: 0表示不返回_id字段。默认情况下,_id字段会被返回,如果不想返回需要显式设置为0。

7. 限制结果集

7.1 limit方法

limit()方法用于限制返回的文档数量。例如,只查询前5个学生:

async function findFirst5Students() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const first5Students = await studentsCollection.find().limit(5).toArray();
        console.log(first5Students);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findFirst5Students();

7.2 skip方法

skip()方法用于跳过指定数量的文档。例如,跳过前3个学生,查询后面的学生:

async function skipFirst3Students() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const skippedStudents = await studentsCollection.find().skip(3).toArray();
        console.log(skippedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

skipFirst3Students();

也可以同时使用limit()skip()方法进行分页查询。例如,每页显示10条数据,查询第2页的数据:

async function paginateStudents() {
    const page = 2;
    const pageSize = 10;
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const paginatedStudents = await studentsCollection.find()
          .skip((page - 1) * pageSize)
          .limit(pageSize)
          .toArray();
        console.log(paginatedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

paginateStudents();

8. 排序查询

使用sort()方法可以对查询结果进行排序。sort()方法接受一个文档作为参数,指定按哪些字段排序以及排序的方向(1表示升序,-1表示降序)。例如,按年龄升序查询学生:

async function sortStudentsByAgeAsc() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const sortedStudents = await studentsCollection.find().sort({ age: 1 }).toArray();
        console.log(sortedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

sortStudentsByAgeAsc();

如果要按年龄降序,成绩升序排序,可以这样写:

async function complexSortStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const sortedStudents = await studentsCollection.find().sort({ age: -1, score: 1 }).toArray();
        console.log(sortedStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

complexSortStudents();

9. 嵌套文档查询

如果文档中包含嵌套结构,查询方式会有所不同。假设students集合中的文档结构如下:

{
    "name": "张三",
    "age": 20,
    "address": {
        "city": "北京",
        "district": "朝阳区"
    }
}

要查询地址在朝阳区的学生,可以这样写:

async function findStudentsInChaoyang() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const chaoyangStudents = await studentsCollection.find({ "address.district": "朝阳区" }).toArray();
        console.log(chaoyangStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsInChaoyang();

这里使用点号(.)来指定嵌套字段的路径。

10. 数组查询

10.1 匹配数组元素

如果文档中包含数组字段,例如学生的爱好数组:

{
    "name": "李四",
    "age": 22,
    "hobbies": ["篮球", "音乐", "阅读"]
}

要查询爱好中有“篮球”的学生,可以这样写:

async function findBasketballLovers() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const basketballLovers = await studentsCollection.find({ hobbies: "篮球" }).toArray();
        console.log(basketballLovers);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findBasketballLovers();

10.2 数组大小查询

使用$size操作符可以查询数组大小符合条件的文档。例如,查询有3个爱好的学生:

async function findStudentsWith3Hobbies() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const studentsWith3Hobbies = await studentsCollection.find({ hobbies: { $size: 3 } }).toArray();
        console.log(studentsWith3Hobbies);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findStudentsWith3Hobbies();

10.3 数组元素全部匹配

有时需要查询数组中所有元素都满足某个条件的文档。例如,查询爱好中同时包含“篮球”和“阅读”的学生,需要使用$all操作符:

async function findAllMatchStudents() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const allMatchStudents = await studentsCollection.find({ hobbies: { $all: ["篮球", "阅读"] } }).toArray();
        console.log(allMatchStudents);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

findAllMatchStudents();

11. 聚合查询

聚合查询可以对文档进行复杂的数据分析和处理。例如,计算学生的平均年龄:

async function calculateAverageAge() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const averageAge = await studentsCollection.aggregate([
            {
                $group: {
                    _id: null,
                    averageAge: { $avg: "$age" }
                }
            }
        ]).toArray();
        console.log(averageAge);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

calculateAverageAge();

在上述代码中,$group操作符用于分组,_id: null表示不进行分组,$avg是聚合操作符,用于计算平均值。

又如,按性别统计学生人数:

async function countStudentsByGender() {
    try {
        await client.connect();
        const db = client.db('school');
        const studentsCollection = db.collection('students');
        const countByGender = await studentsCollection.aggregate([
            {
                $group: {
                    _id: "$gender",
                    count: { $sum: 1 }
                }
            }
        ]).toArray();
        console.log(countByGender);
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

countStudentsByGender();

这里_id: "$gender"表示按gender字段进行分组,$sum: 1用于统计每组的文档数量。

通过以上这些基本操作和示例,你可以对MongoDB的查询功能有一个较为全面的了解,能够根据不同的业务需求进行灵活的文档查询。在实际应用中,还需要根据数据量、性能等因素进一步优化查询语句。