mcpField
M
meteor-mongo-minimongo

meteor-mongo-minimongo

github.com/meteor数据与数据库10293 次安装5 天前更新
代码仓库

关于 meteor-mongo-minimongo

面向 Meteor 开发者的 MongoDB 与 Minimongo 使用指南,说明服务端和客户端的读写差异、索引及响应式数据驱动选择。

主要功能

  1. 01区分服务端与客户端读写 API
  2. 02使用异步 Mongo 操作
  3. 03为分页查询创建索引
  4. 04选择变更流、oplog 或轮询
  5. 05支持排序与查询的排序规则

适用场景

  1. 01编写跨服务端和客户端的查询
  2. 02为大型查询添加分页与索引
  3. 03排查响应式更新的驱动选择
  4. 04实现大小写不敏感的查询

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/meteor/agent-skills --skill meteor-mongo-minimongo

安装后在 Claude Code 中输入/meteor-mongo-minimongo确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
eval-cases.md
selectors-modifiers.md
server-vs-client.md

详细介绍

Mongo 和 Minimongo

Meteor 在同一代码库中提供了两种 Mongo API 实现。服务器通过异步驱动程序与 MongoDB 通信。客户端运行 Minimongo,这是一个内存中的同步 Mongo 模拟器,用于保存订阅发送过来的文档。

决策流程

  1. 这段代码在哪里运行?
    • 仅在服务器端:使用 await Collection.*Async(...)。
    • 仅在客户端:同步使用 Collection.*(...)。
    • 同构代码(在共享代码中 import):使用 await Collection.*Async(...)。 在客户端,操作在本地执行,但仍基于 Promise;在服务器端则会与 Mongo 通信。
  2. 查询是否会选出超过一页的文档?添加 { limit, skip },并添加与选择器匹配的索引。
  3. 是否在客户端从发布中读取数据?使用 find().fetch()(同步),不要使用 await。数据已经在本地。

服务器端读取

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();

服务器端写入

const _id = await Posts.insertAsync({ title, ownerId });
await Posts.updateAsync({ _id }, { $set: { title } });
await Posts.removeAsync({ _id });

客户端读取(Minimongo)

异步 API 可用于同构代码。优先在共享代码中使用它,以便同一行代码在服务器端也能正常运行。

const doc = await Posts.findOneAsync(id);                 // works in shared/client/server
const list = await Posts.find({ ownerId }).fetchAsync();

在客户端,操作会读取内存中的 Minimongo,但异步 API 仍会返回真正的 Promise。await 之后的代码会在稍后的微任务中恢复执行。同步 API 在客户端也可用,但仅限客户端:

const doc = Posts.findOne(id);                            // client-only
const list = Posts.find({ ownerId }).fetch();             // client-only

如果调用作用域本身适合保持同步,并且强制使用 await 会导致异步逻辑扩散到渲染路径中,请选择同步 API。常见情况包括:

  • 消费响应式数据的 React 渲染函数和钩子。
  • Blaze 模板助手。
  • Tracker 自动运行函数。

如果文件也可能在服务器端运行,或所在函数已经是 async,请选择异步 API(findOneAsync、fetchAsync)。

索引

索引仅在服务器端使用。在应用启动时创建索引:

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 mongo)中的 db.posts.find(...).explain("executionStats") 验证所选的查询计划。

响应式数据源:oplog 或变更流

核心驱动边界因版本而异:

Meteor响应式行为
3.0 至 3.4配置了 MONGO_OPLOG_URL 时使用 oplog;否则使用轮询。核心变更流和响应式顺序设置不可用。
3.5+按下方默认顺序为每个查询选择驱动。

Meteor 3.5+ 的默认设置为:

changeStreams -> oplog -> polling

变更流要求 MongoDB 6+ 部署在副本集或分片集群上,观察器未排序,不使用 skip 或 limit,且选择器可由 Minimongo 编译。不符合条件的查询会转而使用 下一个已配置的驱动。只有配置了 MONGO_OPLOG_URL 时,oplog 才可用。

Meteor 3.6(已在 beta.3 的 [email protected] 上验证)也会拒绝用于 Change Streams 的 $where/$near 选择器(RC 版本解决为 [email protected]):Minimongo 无法依据 MongoDB 语义重新匹配实时事件。 Oplog 也会拒绝这些选择器,因此请确认有可用的轮询回退方案。Minimongo 不兼容的 投影也需要回退。MongoDB 支持、但被 Minimongo 拒绝的投影属于驱动边界,不代表 需要重写发布或架构。提出这种更广泛的更改前,请先验证回退方案。测试初始结果和 实时结果;不要仅为强制使用 Change Streams 而移除选择器、投影或分页。 较早的 3.5/beta.1 软件包可能会为 $where/$near 选择错误的驱动;对于受限版本, 请使用受支持的轮询配置,或经授权的兼容升级,然后重新运行完全相同的查询。

在 Meteor 3.5+ 上,可通过以下方式覆盖应用级顺序: METEOR_REACTIVITY_ORDER=oplog,polling,或使用:

{
  "packages": {
    "mongo": {
      "reactivity": ["oplog", "polling"]
    }
  }
}

在 Meteor 3.5+ 上,disable-oplog 软件包只会移除 oplog 步骤,不会禁用变更流。 使用 reactivity: ["polling"] 强制启用轮询。在 Meteor 3.0 至 3.4 上,请勿添加 这些设置;请先升级。

如果核心变更流导致观察器事件重复或登录间歇性断开,请先检查解析到的 mongo 版本,再考虑重写查询或禁用响应式功能。[email protected](Meteor 3.5.2)修复了 对因果主节点快照已涵盖事件的重放问题。较早的 3.5 软件包不包含此修复; 请升级并重新运行失败的操作序列。这不会改变驱动适用条件,也不能成为按时间戳 随意丢弃应用事件的理由。如果问题仍然存在,请捕获观察器的顺序;原因不明时请使用 meteor-debugging。

排序规则(Meteor 3.5+)

使用 collation,在 Mongo 和 Minimongo 中进行区域设置感知或不区分大小写的 选择和排序。请为服务器查询创建使用相同排序规则的索引:

const collation = { locale: "en", strength: 2 };
const users = await Users.find(
  { email: "[email protected]" },
  { collation },
).fetchAsync();

await Users.createIndexAsync({ email: 1 }, { collation });

Minimongo 支持 locale、1 至 3 的 strength、caseLevel、 numericOrdering 和 caseFirst。其他 Mongo 排序规则选项仅由服务器支持, 并会被 Minimongo 忽略。

反模式

  • 在服务器上使用同步 Mongo。该功能已在 Meteor 3 中移除。
  • 在共享代码中使用同步 Mongo(findOne、insert、update、remove)。 文件一旦在服务器上导入,就会出问题。
  • 在服务器上执行无界 find。始终使用 limit。
  • 发布时忘记使用 fields 投影。始终指定投影。
  • 假设异步 Minimongo API 会在当前调用中恢复执行。即使底层读取发生在本地,它仍会返回 Promise。

另请参阅

  • references/server-vs-client.md
  • references/selectors-modifiers.md
  • references/eval-cases.md

评论

支持 Markdown