Skip to content

MongoDB - 查询文档

查询是从数据库中检索数据的过程。MongoDB 提供丰富而强大的查询语言,可帮助您找到所需的精确文档。本章涵盖查询的基础知识,从基本查找操作到复杂的逻辑条件。

我们首先向 posts 集合插入一个真实的数据集。我们将使用 insertMany 等现代方法和适当的数据类型(如 Number、Boolean、Array 等)。

db.posts.insertMany([
{
title: "Introduction to MongoDB",
author: "Chris",
tags: ["mongodb", "database", "nosql"],
views: 1500,
isPublished: true,
comments: [
{ user: "Alice", text: "Great overview!" },
{ user: "Bob", text: "Very helpful, thanks." }
]
},
{
title: "Advanced Aggregation",
author: "Sarah",
tags: ["mongodb", "aggregation", "advanced"],
views: 750,
isPublished: true
},
{
title: "Schema Design Best Practices",
author: "Chris",
tags: ["mongodb", "schema", "modeling"],
views: 2200,
isPublished: true
},
{
title: "Upcoming Features",
author: "Chris",
tags: ["mongodb", "future"],
views: 50,
isPublished: false
}
]);

find(query, projection) 是主要的查询方法。它返回一个游标(cursor),该游标是指向结果集的指针。findOne(query, projection) 是一种便捷的替代方法,它只返回与查询匹配的第一个文档,如果没有找到匹配项,则返回 null。

// 查找集合中的所有文档(空查询文档)
> db.posts.find({})
// 查找 'Chris' 撰写的第一个文档
> db.posts.findOne({ author: "Chris" })
// 注意:mongosh 会自动格式化 JSON 输出以提高可读性。
// 传统的 .pretty() 方法仍然有效,但已不再必需。

要创建更具体的查询,您可以使用查询操作符。它们相当于 SQL 中的 WHERE 子句。

操作语法示例(在 posts 集合上)关系型数据库(RDBMS)等效
相等{ : }db.posts.find({ author: “Sarah” })WHERE author = ‘Sarah’
小于{ : { $lt: } }db.posts.find({ views: { $lt: 1000 } })WHERE views < 1000
大于或等于{ : { $gte: } }db.posts.find({ views: { $gte: 1500 } })WHERE views >= 1500
不等于{ : { $ne: } }db.posts.find({ author: { $ne: “Chris” } })WHERE author != ‘Chris’
值在数组中{ : { $in: [, ] } }db.posts.find({ author: { $in: [“Chris”, “Sarah”] } })WHERE author IN (‘Chris’, ‘Sarah’)
值不在数组中{ : { $nin: [, ] } }db.posts.find({ tags: { $nin: [“future”, “draft”] } })WHERE tag is not in (‘future’, ‘draft’)

默认情况下,当您在查询文档中提供多个字段时,MongoDB 会执行逻辑 AND 操作。以下查询会查找由 ‘Chris’ 撰写且已发布的文章。

> db.posts.find({ author: "Chris", isPublished: true })

要查找匹配多个条件中至少一个的文档,请使用 $or 操作符,它接受一个查询文档数组。

// 查找浏览量小于 100 或尚未发布的文章
> db.posts.find({
$or: [
{ views: { $lt: 100 } },
{ isPublished: false }
]
})

$nor 操作符查找不匹配数组中所有条件的文档。它的意思是“既不满足这个,也不满足那个”。

// 查找作者不是 'Sarah' 且不包含 'nosql' 标签的文章
> db.posts.find({
$nor: [
{ author: 'Sarah' },
{ tags: 'nosql' }
]
})

要查找数组包含特定元素的文档,只需查询该值即可。

// 查找所有带有 'mongodb' 标签的文章
> db.posts.find({ tags: "mongodb" })

使用点表示法(dot notation)查询嵌入式文档或文档数组中的字段。

// 查找用户 'Alice' 发表过评论的文章
> db.posts.find({ "comments.user": "Alice" })

一个简单的查询,例如 { 'comments.user': 'Alice', 'comments.text': '...' },可能会匹配到如果一个评论是 Alice 写的,而另一个评论包含指定的文本。为了确保数组中的单个元素满足多个条件,请使用 $elemMatch。

// 查找包含 'Bob' 评论中带有“helpful”一词的文章
// 这确保了 'user' 和 'text' 条件应用于同一个评论对象
> db.posts.find({
comments: {
$elemMatch: { user: "Bob", text: /helpful/ }
}
})

以下是在典型 Node.js 应用程序中使用官方 mongodb 驱动程序执行查询的方式。首先,请确保您已安装该驱动程序:npm install mongodb。

const { MongoClient } = require('mongodb');
// 替换为您的 MongoDB 部署的连接字符串。
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const database = client.db('yourDbName'); // 替换为您的数据库名称
const posts = database.collection('posts');
// 查询 Chris 撰写的热门已发布文章
const query = {
author: 'Chris',
isPublished: true,
views: { $gte: 1000 }
};
const cursor = posts.find(query);
// 如果未找到文档,则打印消息
if ((await posts.countDocuments(query)) === 0) {
console.log("No documents found!");
}
// 打印每个文档
for await (const doc of cursor) {
console.dir(doc);
}
} finally {
// 确保当您完成/出错时客户端会关闭
await client.close();
}
}
run().catch(console.dir);

要了解 MongoDB 如何执行您的查询以及识别性能瓶颈,请使用 explain() 方法。这对于检查您的查询是否有效利用索引至关重要。

> db.posts.find({ author: 'Chris', views: { $gt: 1000 } }).explain('executionStats')
// 分析输出中的 'executionStats'。
// 'winningPlan' 中显示 'IXSCAN'(索引扫描)远优于 'COLLSCAN'(集合扫描)。