Overview
您可以执行查找操作,以便从 MongoDB 数据库检索数据。您可以通过调用 find()
或 findOne()
方法来执行查找操作,以便根据一组条件来匹配文档。
提示
互动实验室
本页包括一个简短的交互式实验,演示如何使用 find()
方法检索数据。您无需安装 MongoDB 或代码编辑器,即可直接在浏览器窗口中完成此实验。
若要启动实验室,请单击页面顶部的“Open Interactive Tutorial”按钮。要将实验室扩展为全屏格式,请单击实验室窗格右上角的全屏按钮 (⛶)。
您还可以通过指定可选参数或链接其他方法,进一步指定查找操作返回的信息,如以下指南所示:
还可以使用聚合操作来检索数据。这种操作类型让您可以对匹配的数据应用一套有序的转换管道。
如果要监测有无符合特定条件的数据传入数据库,则可以使用监控(watch)操作。这样,当有匹配的数据插入时,您可实时收到通知。
注意
您的查询操作可能会返回对包含匹配文档的游标的引用。要学习;了解如何检查游标中存储的数据,请参阅从游标访问数据页面。
您可以使用 Node.js 驱动程序进行连接并对以下环境中托管的部署执行读取操作:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
MongoDB Enterprise:基于订阅、自行管理的 MongoDB 版本
MongoDB Community:source-available、免费使用且可自行管理的 MongoDB 版本
如需了解有关在 Atlas 用户界面中对 MongoDB Atlas 托管的部署执行读取操作的更多信息,请参阅查看、过滤和排序文档。
查找文档
您可对 Collection
对象调用 find()
方法。此方法接受用于描述待检索文档的查询文档。有关如何指定查询文档的更多信息,请参阅指定查询指南。
提示
无查询条件
要执行没有查询条件的查找操作,您可以在查找方法参数中传递空查询或省略查询文档。
以下操作均返回 myColl
集合中的所有文档:
myColl.find(); // no query myColl.find({}); // empty query
如果不传递查询或向 findOne()
方法传递空查询,则该操作将从集合中返回单个文档。
即使传递空查询,也可以将游标方法链接到查找操作。示例,以下代码显示了如何在执行接收空查询参数的查找操作时指定投影:
const projectFields = { _id: 0, field1: 1 }; const findResult = await myColl.findOne().project(projectFields);
有关投影文档字段的更多信息,请参阅指定要返回的字段指南。
find()
方法会返回一个Cursor
实例,您可以从该实例访问匹配的文档。findOne()
方法会返回一个Promise
实例,您可以解析该实例以访问匹配的文档;或者,如果没有匹配项,该实例则会返回null
值。
例子
一家披萨餐厅想查找 Lemony Snicket 昨天订购的所有披萨。他们在 orders
集合上运行以下 find()
查询:
// Search for orders by name and within a specific date range const findResult = orders.find({ name: "Lemony Snicket", date: { $gte: new Date(new Date().setHours(00, 00, 00)), $lt: new Date(new Date().setHours(23, 59, 59)), }, });
操作返回后,findResult
变量将引用 Cursor
。 您可以打印使用 for await...of
语法检索到的文档,如下所示:
for await (const doc of findResult) { console.log(doc); }
输出可能如下所示:
[ { name: "Lemony Snicket", type: "horseradish pizza", qty: 1, status: "delivered", date: ... }, { name: "Lemony Snicket", type: "coal-fired oven pizza", qty: 3, status: "canceled", date: ...}, ... ]
findOne() 示例:完整文件
注意
设置示例
此示例使用连接 URI 连接到MongoDB实例。要学习;了解有关连接到MongoDB实例的更多信息,请参阅连接到MongoDB指南。此示例还使用Atlas示例数据集包含的 movies
sample_mflix
数据库中的 集合。您可以按照Atlas入门指南,将它们加载到MongoDB Atlas免费套餐上的数据库中。
以下完整文件示例从 movies
集合中查找单个文档。它使用以下参数:
用于匹配
title
值为'The Room'
的文档的筛选器。排序,按评分按降序组织匹配的文档,因此,如果我们的查询匹配多个文档,返回的文档将是评分最高的文档。
从返回的文档中显式排除
_id
字段并显式仅包含title
和imdb
对象(及其嵌入式字段)的投影。
import { MongoClient } from "mongodb"; // Replace the uri string with your MongoDB deployment's connection string. const uri = "<connection string uri>"; const client = new MongoClient(uri); async function run() { try { // Get the database and collection on which to run the operation const database = client.db("sample_mflix"); const movies = database.collection("movies"); // Query for a movie that has the title 'The Room' const query = { title: "The Room" }; const options = { // Sort matched documents in descending order by rating sort: { "imdb.rating": -1 }, // Include only the `title` and `imdb` fields in the returned document projection: { _id: 0, title: 1, imdb: 1 }, }; // Execute query const movie = await movies.findOne(query, options); // Print the document returned by findOne() console.log(movie); } finally { await client.close(); } } run().catch(console.dir);
import { MongoClient } from "mongodb"; // Replace the uri string with your MongoDB deployment's connection string. const uri = "<connection string uri>"; const client = new MongoClient(uri); interface IMDB { rating: number; votes: number; id: number; } export interface Movie { title: string; year: number; released: Date; plot: string; type: "movie" | "series"; imdb: IMDB; } type MovieSummary = Pick<Movie, "title" | "imdb">; async function run(): Promise<void> { try { const database = client.db("sample_mflix"); // Specifying a Schema is always optional, but it enables type hinting on // finds and inserts const movies = database.collection<Movie>("movies"); const movie = await movies.findOne<MovieSummary>( { title: "The Room" }, { sort: { rating: -1 }, projection: { _id: 0, title: 1, imdb: 1 }, } ); console.log(movie); } finally { await client.close(); } } run().catch(console.dir);
运行上述示例将产生以下输出:
{ title: 'The Room', imdb: { rating: 3.5, votes: 25673, id: 368226 } }
find() 示例:完整文件
注意
设置示例
此示例使用连接 URI 连接到MongoDB实例。要学习;了解有关连接到MongoDB实例的更多信息,请参阅连接到MongoDB指南。此示例还使用Atlas示例数据集包含的 movies
sample_mflix
数据库中的 集合。您可以按照Atlas入门指南,将它们加载到MongoDB Atlas免费套餐上的数据库中。
以下完整文件示例从 movies
集合中查找文档。它使用以下参数:
用于匹配
runtime
值小于 15 分钟的文档的筛选器。排序,按标题升序组织返回的文档(按字母顺序,“A”在“Z”之前,“1”在“9”之前)。
从返回的文档中显式排除
_id
字段并显式仅包含title
和imdb
对象(及其嵌入式字段)的投影。
1 import { MongoClient } from "mongodb"; 2 3 // Replace the uri string with your MongoDB deployment's connection string. 4 const uri = "<connection string uri>"; 5 6 const client = new MongoClient(uri); 7 8 async function run() { 9 try { 10 11 // Get the database and collection on which to run the operation 12 const database = client.db("sample_mflix"); 13 const movies = database.collection("movies"); 14 15 // Query for movies that have a runtime less than 15 minutes 16 const query = { runtime: { $lt: 15 } }; 17 const sortFields = { title: 1 }; 18 const projectFields = { _id: 0, title: 1, imdb: 1 }; 19 20 // Execute query 21 const cursor = movies.find(query).sort(sortFields).project(projectFields); 22 23 // Print a message if no documents were found 24 if ((await movies.countDocuments(query)) === 0) { 25 console.log("No documents found!"); 26 } 27 28 // Print returned documents 29 for await (const doc of cursor) { 30 console.dir(doc); 31 } 32 33 } finally { 34 await client.close(); 35 } 36 } 37 run().catch(console.dir);
1 import { MongoClient } from "mongodb"; 2 3 // Replace the uri string with your MongoDB deployment's connection string. 4 const uri = "<connection string uri>"; 5 6 const client = new MongoClient(uri); 7 8 type Minutes = number; 9 10 interface IMDB { 11 rating: number; 12 votes: number; 13 id: number; 14 } 15 16 interface Movie { 17 title: string; 18 imdb: IMDB; 19 runtime: Minutes; 20 } 21 22 async function run() { 23 try { 24 const database = client.db("sample_mflix"); 25 const movies = database.collection<Movie>("movies"); 26 27 const query = { runtime: { $lt: 15 } }; 28 const sortFields = { title: 1 }; 29 const projectFields = { _id: 0, title: 1, imdb: 1 }; 30 31 const cursor = movies.find<Movie>(query).sort(sortFields).project(projectFields); 32 33 if ((await movies.countDocuments(query)) === 0) { 34 console.warn("No documents found!"); 35 } 36 37 for await (const doc of cursor) { 38 console.dir(doc); 39 } 40 } finally { 41 await client.close(); 42 } 43 } 44 run().catch(console.dir);
运行上述示例将产生以下输出:
{ title: '10 Minutes', imdb: { rating: 7.9, votes: 743, id: 339976 } } { title: '3x3', imdb: { rating: 6.9, votes: 206, id: 1654725 } } { title: '7:35 in the Morning', imdb: { rating: 7.3, votes: 1555, id: 406501 } } { title: '8', imdb: { rating: 7.8, votes: 883, id: 1592502 } } ...
注意
在迭代游标之前,必须将游标方法(如 sort()
、limit()
、skip()
或 project()
)链接到读操作。如果在迭代游标后指定游标方法,则该设置不会应用读取操作。
更多信息
有关 findOne()
和 find()
方法的更多信息,请参阅以下服务器手册文档:
汇总文档中的数据
如果要运行自定义处理管道以从数据库中获取数据,可以使用 aggregate()
方法。此方法接受依序运行的聚合表达式。通过这些表达式,可以对集合中的结果数据进行筛选、分组和排列。
例子
一家披萨餐厅想按需运行状态报告来总结过去一周的披萨订单。为此,它们会对 orders
集合运行以下 aggregate()
查询,从而获取每个不同“状态”字段的总和:
// Group orders by status within the last week const aggregateResult = orders.aggregate([ { $match: { date: { $gte: new Date(new Date().getTime() - 1000 * 3600 * 24 * 7), $lt: new Date(), }, }, }, { $group: { _id: "$status", count: { $sum: 1, }, }, }, ]);
操作返回后,aggregateResult
变量将引用 Cursor
。 您可以打印使用 for await...of
语法检索到的文档,如下所示:
for await (const doc of aggregateResult) { console.log(doc); }
输出可能如下所示:
[ { _id: 'delivering', count: 5 }, { _id: 'delivered', count: 37 }, { _id: 'created', count: 9 } ]
更多信息
监控数据变化
您可以使用watch()
方法来监视集合,以了解对符合特定条件的集合所做的更改。这些更改包括插入、更新、替换和删除的文档。 您可以向此方法传递一个聚合命令管道,每当对集合执行写入操作时,该管道都会对更改的数据按顺序运行。
例子
一家披萨餐厅希望在收到新的披萨订单时获得通知。为了实现这一目标,他们创建了一个聚合管道来过滤插入操作并返回特定字段。他们将此管道传递给在 orders
集合上调用的watch()
方法,如下所示:
// Set up a change stream to listen for new order insertions const changeStream = orders.watch([ { $match: { operationType: "insert" } }, { $project: { "fullDocument.name": 1, "fullDocument.address": 1, }, }, ]); changeStream.on("change", change => { const { name, address } = change.fullDocument; console.log(`New order for ${name} at ${address}.`); });