基础目录

供应商、产品与自制备料——记录的其余部分所指向的那几份参照清单。

基础目录,是一家餐厅列成清单、而不是拿去测量的那些东西:谁来送货、什么东西进了 门、厨房自己做了什么。这里没有任何东西是一次查验或一次读数。这些是其他一切都会 点到名的那些行,所以它们通常是你最先加载的东西,也是最后才会变的东西。

集合权限范围一条记录是什么
supplierssuppliers:read一家来送货的公司,以及怎么联系它。
productsproducts:read餐厅收到并使用的某样东西,按名字。
preparationspreparations:read厨房自己做的某样东西,带着它的保质期和过敏原。

这三个共用同一个快照信封iddeletedcapturedAtreceivedAtsequence 以及其余字段,都摆在下文描述的 data 旁边。

suppliers

餐厅录入的每一家供应商一条记录,不论最近有没有东西从他们那里送到。

字段类型含义
namestring, 必填餐厅给这家供应商起的名字。自由文本,不是一份工商登记。
isDeletedboolean, 必填应用自己的停用标记。不是信封上的 deleted——见下文。
contactMethodsobject[]怎么联系他们。每一项是 { "type": string, "value": string }
accountNumberstring | null餐厅在这家供应商那里的账户,在录入了一个的时候。
{
  "id": "1f3c2a76-5b94-4b0e-9c1a-6d8f0a2e7b31",
  "collection": "suppliers",
  "deleted": false,
  "capturedAt": "1789431600214",
  "receivedAt": "1789431604771",
  "sequence": "412",
  "data": {
    "name": "Metro Nanterre",
    "isDeleted": false,
    "contactMethods": [
      { "type": "phone", "value": "+33 1 41 20 30 40" },
      { "type": "email", "value": "commandes@example.test" }
    ],
    "accountNumber": "FR-884213"
  }
}

contactMethods[].type 不是一个枚举。 schema 只说了 string,就到此为止,而 上面那些值是一种示意,不是一份清单。对它做分支时带上一个兜底分支,并且不管 type 是怎么写的,都把 value 显示出来。

一条收货记录把它的供应商以 { id, name } 的形式内嵌进来—— 够放到屏幕上,仅此而已。账户编号和电话号码住在这个集合里。

products

餐厅收到并使用的东西。这条记录就像它看上去那么薄。

字段类型含义
namestring, 必填餐厅给这个产品起的名字。
isDeletedboolean, 必填应用的停用标记。见下文。
{
  "id": "6b0d4ea2-91c7-4f3d-a0be-2c5f7d1e8a44",
  "collection": "products",
  "deleted": false,
  "capturedAt": "1789431980551",
  "receivedAt": "1789432001903",
  "sequence": "413",
  "data": {
    "name": "Beurre doux 250 g",
    "isDeleted": false
  }
}

整条记录就这些:没有编号、没有类别、没有单位、没有供应商。如果你的模型需要其中 任何一样,那得由你自己拿着,以信封上的 id 为键。

没有别的东西会按 id 指向一个产品。 一条收货记录把被测量的对象记成 temperatureRecords[].product,那是查验当时打出来的自由文本——见 收货记录。把它和这份清单对上,是你这边的字符串活儿,而且 「Beurre doux 250 g」不是「beurre doux」。你非做不可就做,但不要把结果呈现成一次 连接。

preparations

在店里做出来、而不是收进来的东西——一份酱汁、一锅高汤、一块肉冻派。

字段类型含义
namestring, 必填厨房给这份备料起的名字。
lifespannumber, 必填它能放多久。一个光秃秃的数字。
allergensstring[]它含有什么。自由字符串,不是一个封闭集合。
isDeletedboolean, 必填应用的停用标记。见下文。
{
  "id": "c47e8b13-0a52-4d96-8f1b-73ae2905cd6f",
  "collection": "preparations",
  "deleted": false,
  "capturedAt": "1789455120087",
  "receivedAt": "1789455133642",
  "sequence": "418",
  "data": {
    "name": "Sauce béarnaise",
    "lifespan": 3,
    "allergens": ["oeuf", "lait"],
    "isDeleted": false
  }
}

lifespan 不带单位。 schema 给你一个数字,却没有给你任何可以拿来解释它的东 西。不要因为三看起来像天数就印出「3 天」——请为你正在读的那家餐厅确认应用用它表示 的到底是什么,如果确认不了,就老老实实地把这一点标出来。

allergens 是一个字符串列表,不是一份法规清单。 这些条目来自应用,用的是这 家餐厅的语言。在没有核对这些字符串究竟写了什么之前,不要把它们映射到那十四种具名 过敏原上;也不要把一个空数组当成一次通过了的过敏原检查——它同样可能意味着没有人 填过。

isDeleted 不是 deleted

这一页上的每个集合都带着这两者,它们的含义不同,而一个只按其中一个来筛的使用方, 会得到一份错的清单。

  • 信封上的 deleted,是这份影子副本的墓碑。true 表示这条记录在应用里被删除 了,而 data 已经不在。它正是你得知某个东西消失了的途径——规则在 信封那一页上。
  • data 里面的 isDeleted,是应用自己打在这一行上的软删除标记。记录仍然在, 仍然有它的名字,而且仍然带着 deleted: false 送达。是餐厅把它停用了:它不再出现 在选择器里,但被留了下来,好让老记录仍然解得开。

所以两个都要筛。只认 deleted,你的供应商清单就会塞满餐厅两年前就不再用的供应 商。只认 isDeleted,你就会留下那些被彻底删掉的行,因为一块墓碑没有 data 可以 让你从里面读出那个标记。

不过,请把停用的那些行留着,而不是丢掉。去年三月的一条收货记录,仍然点着一家今天 isDeleted: true 的供应商的名字,而把那个名字解出来,正是你持有这份清单的全部 理由。

怎么读这份目录

这三个都很小、变得很慢,而且几乎其他一切都需要它们,这让它们既是一次同步里最廉价 的那部分,也是最容易在不知不觉间弄错的那部分。

  • 先走它们,留住它们,再按一个节奏去刷新它们。 一家餐厅的整份目录,在 limit=100 下不过是几页。把它以信封上的 id 为键存在你自己的库里,并且从那里 去解名字,而不是每条记录取一次。
  • 名字会变,id 不会。 name 是餐厅在营业中就会改的自由文本。把 id 存下来作 为你的键,把名字当作一个你会去刷新的标签——绝不要把它当成用来做连接的东西。
  • 缺席在这里同样是含糊的。 一家没有出现的供应商,可能从来没被录入过,也可能 还没到我们这里。在你把一个计数报出去之前,先看那条提醒

最后更新于 2026-09-20。