meteor-mongo-minimongo
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMongo and Minimongo
Mongo与Minimongo
Meteor ships two implementations of the Mongo API in one codebase. The server
talks to MongoDB through an async driver. The client runs Minimongo, an
in-memory synchronous Mongo emulator that holds the documents that
subscriptions have shipped.
Meteor在一个代码库中提供了两种Mongo API实现。服务器通过异步驱动连接MongoDB。客户端运行Minimongo,这是一个内存中的同步Mongo模拟器,用于存储订阅推送的文档。
Decision flow
决策流程
- Where does this code run?
- Server-only: use .
await Collection.*Async(...) - Client-only: use synchronously.
Collection.*(...) - Isomorphic (in shared code): use
import. On the client the work is local but still Promise-based; on the server it talks to Mongo.await Collection.*Async(...)
- Server-only: use
- Does the query select more than a page of documents? Add and an index that matches the selector.
{ limit, skip } - Are you reading from a publication on the client? Use (sync) without
find().fetch(). The data is already local.await
- 代码运行位置?
- 仅服务器端:使用。
await Collection.*Async(...) - 仅客户端:同步使用。
Collection.*(...) - 同构代码(在共享代码中通过引入):使用
import。客户端的操作是本地执行,但仍基于Promise;服务器端则直接与Mongo交互。await Collection.*Async(...)
- 仅服务器端:使用
- 查询是否选取超过一页的文档?添加以及与选择器匹配的索引。
{ limit, skip } - 是否在客户端从发布中读取数据?使用(同步),无需
find().fetch()。数据已存储在本地。await
Server reads
服务器端读取
javascript
const doc = await Posts.findOneAsync(id);
const list = await Posts.find({ ownerId }, {
fields: { title: 1 }, sort: { createdAt: -1 }, limit: 50,
}).fetchAsync();
const count = await Posts.find({ ownerId }).countAsync();javascript
const doc = await Posts.findOneAsync(id);
const list = await Posts.find({ ownerId }, {
fields: { title: 1 }, sort: { createdAt: -1 }, limit: 50,
}).fetchAsync();
const count = await Posts.find({ ownerId }).countAsync();Server writes
服务器端写入
javascript
const _id = await Posts.insertAsync({ title, ownerId });
await Posts.updateAsync({ _id }, { $set: { title } });
await Posts.removeAsync({ _id });javascript
const _id = await Posts.insertAsync({ title, ownerId });
await Posts.updateAsync({ _id }, { $set: { title } });
await Posts.removeAsync({ _id });Client reads (Minimongo)
客户端读取(Minimongo)
The async API is isomorphic. Prefer it in shared code so the same line works
on the server.
javascript
const doc = await Posts.findOneAsync(id); // works in shared/client/server
const list = await Posts.find({ ownerId }).fetchAsync();On the client, the operation reads in-memory Minimongo but the async API still
returns a real Promise. Code after resumes in a later microtask. The
sync API also works client-side, but only there:
awaitjavascript
const doc = Posts.findOne(id); // client-only
const list = Posts.find({ ownerId }).fetch(); // client-onlyPick sync when the calling scope is naturally sync and forcing
would cascade async into a render path. Common cases:
await- React render functions and hooks that consume reactive data.
- Blaze template helpers.
- Tracker autoruns.
Pick async (, ) when the file might also run on
the server, or the containing function is already .
findOneAsyncfetchAsyncasync异步API是同构的。在共享代码中优先使用,以便同一代码行可在服务器端运行。
javascript
const doc = await Posts.findOneAsync(id); // 可在共享/客户端/服务器端运行
const list = await Posts.find({ ownerId }).fetchAsync();在客户端,操作读取内存中的Minimongo数据,但异步API仍会返回真实的Promise。之后的代码会在后续微任务中恢复执行。同步API也可在客户端使用,但仅限客户端:
awaitjavascript
const doc = Posts.findOne(id); // 仅限客户端
const list = Posts.find({ ownerId }).fetch(); // 仅限客户端当调用环境本身是同步的,强制使用会将异步逻辑渗透到渲染路径时,选择同步API。常见场景:
await- React渲染函数和消费响应式数据的hooks。
- Blaze模板助手。
- Tracker自动运行函数。
当文件可能同时在服务器端运行,或包含函数已为时,选择异步API(、)。
asyncfindOneAsyncfetchAsyncIndexes
索引
Indexes are server-side. Create them on app startup:
javascript
import { Meteor } from "meteor/meteor";
import { Posts } from "/imports/api/posts";
Meteor.startup(async () => {
await Posts.createIndexAsync({ ownerId: 1, createdAt: -1 });
await Posts.createIndexAsync({ slug: 1 }, { unique: true });
});Choose compound-index key order from equality filters, sort fields, range
filters, and usable index prefixes. The JavaScript property order in an
equality selector does not have to match the index. Verify the chosen plan in
the Mongo shell () with
.
meteor mongodb.posts.find(...).explain("executionStats")索引是服务器端的。在应用启动时创建:
javascript
import { Meteor } from "meteor/meteor";
import { Posts } from "/imports/api/posts";
Meteor.startup(async () => {
await Posts.createIndexAsync({ ownerId: 1, createdAt: -1 });
await Posts.createIndexAsync({ slug: 1 }, { unique: true });
});根据等值筛选、排序字段、范围筛选和可用的索引前缀选择复合索引的键顺序。不等值选择器中的JavaScript属性顺序无需与索引匹配。在Mongo shell()中使用验证所选执行计划。
meteor mongodb.posts.find(...).explain("executionStats")Reactivity source: oplog or change streams
响应式数据源:oplog或change streams
The core driver boundary is release-specific:
| Meteor | Reactive behavior |
|---|---|
| 3.0 through 3.4 | Uses oplog when |
| 3.5+ | Chooses a driver per query in the default order below. |
Meteor 3.5+ defaults to:
text
changeStreams -> oplog -> pollingChange streams require MongoDB 6+ on a replica set or sharded cluster, an
unordered observer, no or , and a selector Minimongo can compile.
An ineligible query falls through to the next configured driver. Oplog is
available only when is configured.
skiplimitMONGO_OPLOG_URLOn Meteor 3.5+, override the app-wide order with
or:
METEOR_REACTIVITY_ORDER=oplog,pollingjson
{
"packages": {
"mongo": {
"reactivity": ["oplog", "polling"]
}
}
}On Meteor 3.5+, the package removes only the oplog step. It
does not disable change streams. Use to force
polling. On Meteor 3.0 through 3.4, do not add these settings; upgrade first.
disable-oplogreactivity: ["polling"]核心驱动边界因版本而异:
| Meteor | 响应式行为 |
|---|---|
| 3.0 至 3.4 | 配置 |
| 3.5+ | 按以下默认顺序为每个查询选择驱动。 |
Meteor 3.5+默认顺序:
text
changeStreams -> oplog -> pollingChange streams要求MongoDB 6+运行在副本集或分片集群上,使用无序观察者,无或,且选择器可被Minimongo编译。不符合条件的查询会自动切换到下一个配置的驱动。仅当配置时,oplog才可用。
skiplimitMONGO_OPLOG_URL在Meteor 3.5+上,可通过或以下配置覆盖应用级顺序:
METEOR_REACTIVITY_ORDER=oplog,pollingjson
{
"packages": {
"mongo": {
"reactivity": ["oplog", "polling"]
}
}
}在Meteor 3.5+上,包仅移除oplog步骤,不会禁用change streams。使用强制使用轮询。在Meteor 3.0至3.4版本中,请勿添加这些设置,建议先升级版本。
disable-oplogreactivity: ["polling"]Collation (Meteor 3.5+)
排序规则(Meteor 3.5+)
Use for locale-aware or case-insensitive selectors and sorting on
both Mongo and Minimongo. Back the server query with an index created using
the same collation:
collationjavascript
const collation = { locale: "en", strength: 2 };
const users = await Users.find(
{ email: "Alice@Example.COM" },
{ collation },
).fetchAsync();
await Users.createIndexAsync({ email: 1 }, { collation });Minimongo supports , strength 1 through 3, ,
, and . Other Mongo collation options are
server-only and are ignored by Minimongo.
localecaseLevelnumericOrderingcaseFirst在Mongo和Minimongo上,使用实现支持区域设置或大小写不敏感的选择器与排序。服务器端查询需搭配使用相同排序规则创建的索引:
collationjavascript
const collation = { locale: "en", strength: 2 };
const users = await Users.find(
{ email: "Alice@Example.COM" },
{ collation },
).fetchAsync();
await Users.createIndexAsync({ email: 1 }, { collation });Minimongo支持、强度1至3、、和。其他Mongo排序规则选项仅在服务器端可用,会被Minimongo忽略。
localecaseLevelnumericOrderingcaseFirstAnti-patterns
反模式
- Use sync Mongo on the server. Removed in Meteor 3.
- Use sync Mongo (,
findOne,insert,update) in shared code. Breaks the moment the file is imported on the server.remove - Unbounded on the server. Always
find.limit - Forget projection when publishing. Always project.
fields - Assume the async Minimongo API resumes inline. It returns a Promise even though the underlying read is local.
- 在服务器端使用同步Mongo。Meteor 3已移除该功能。
- 在共享代码中使用同步Mongo(、
findOne、insert、update)。一旦文件在服务器端引入,代码会崩溃。remove - 在服务器端使用无限制的。始终添加
find。limit - 发布时忘记使用投影。始终添加投影。
fields - 假设Minimongo异步API会立即恢复执行。即使底层读取是本地操作,它仍会返回Promise。
See also
另请参阅
references/server-vs-client.mdreferences/selectors-modifiers.mdreferences/eval-cases.md
references/server-vs-client.mdreferences/selectors-modifiers.mdreferences/eval-cases.md