炸锅

那些炸锅和在它们上面做的油品质量检查——两个集合,以及为什么测得的值可以缺失、而那个决定绝不会。

煎炸用油会在使用中劣化,过了某个点就必须过滤掉或者倒掉。餐厅对它做检测、决定怎么 办,并且把两者都记下来。两个集合:那些炸锅,以及在它们上面做的那些检查。

集合权限范围一条记录是什么
fryer-equipmentfryer-equipment:read一台炸锅。
fryer-checksfryer-checks:read对其中一台做的一次油品质量检查,以及当时的决定。

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

fryer-equipment

炸锅本身,按餐厅把它们列出来的样子。一条很短的记录——一个名字、在列表里的一个位 置,以及它站在哪里。

字段类型含义
indexinteger, 必填这台炸锅在列表里的位置,按应用给它们排的顺序。
namestring, 必填餐厅管它叫什么。
areaIdstring | null它所在的那个区域。在一家不把自己划分成区域的餐厅里为 null
isDeletedboolean, 必填应用自己的软删除。请读下面那条说明。
{
  "id": "6b1d0f54-8e27-4c93-a7b0-52fd3e1c9a86",
  "collection": "fryer-equipment",
  "deleted": false,
  "capturedAt": "1789598411206",
  "receivedAt": "1789598603471",
  "sequence": "1",
  "data": {
    "index": 1,
    "name": "Friteuse gauche",
    "areaId": "7d2c0b61-4e8a-49f3-9c27-5a1b8e60d3f4",
    "isDeleted": false
  }
}

这里没有阈值。设备不一样,一台炸锅既不带 min 也不带 max:记录上没有任何东西说一个好的油品读数是什么。一次检查是否可接受,是餐厅的 判断,而它留下的唯一痕迹,就是他们采取的那个行动。

isDeleted 不是信封上的 deleted 一台被餐厅移走的炸锅,回来时是 isDeleted: truedeleted: false:仍然是一条活着的记录,描述的是一台已经不再 服役的炸锅。两个都要筛,并且把移走的那些留着——老的检查仍然指向它们。

fryer-checks

对一台炸锅做的一次检查:这次检测显示了什么,以及为此做了什么。

字段类型含义
timestampstring, 必填这次检查是什么时候做的,以字符串表示的 Unix 毫秒时间戳。
testValuestring | null检测显示了什么,以文本记录。什么都没测时为 null
actionstring, 必填对这油做了什么决定——把它过滤掉、把它换掉、就这么留着。
fryerEquipmentIdstring, 必填被检查的那台炸锅。
userIdstring | null做这次检查的那名员工,在应用记下了一个的时候。
{
  "id": "e07a5c92-4f61-48b8-9d3a-b18c60e5427f",
  "collection": "fryer-checks",
  "deleted": false,
  "capturedAt": "1789777348215",
  "receivedAt": "1789777510964",
  "sequence": "2",
  "data": {
    "timestamp": "1789777200000",
    "testValue": "18",
    "action": "Filtration de l'huile",
    "fryerEquipmentId": "6b1d0f54-8e27-4c93-a7b0-52fd3e1c9a86",
    "userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
  }
}

testValue 是一个字符串,不是一个数字。 它是试纸或者探针显示出来的东西,以 文本记下,而记录既不带单位也不带刻度——用试纸的餐厅和用极性化合物检测仪的餐厅, 都落在这里。把它当文本留着。跨餐厅把它解析成浮点数,只会给你一列彼此之间无法比较 的值。

action 是自由文本,用的是这家餐厅的语言。schema 不对它做约束,所以请读这个 值,而不要拿它去比对一份你自己的清单——也不要拿你在一家餐厅的数据里看到的东西 建枚举。

一次没有值的检查意味着什么

testValue 可以为 null,而 action 是必填的,这个不对称正是你要围着它来设计的那 件事。一次检查可以被记成一个采取过的行动,背后却没有任何测得的值:有人把油换了, 因为它看起来不对劲,因为到周末了,因为反正那台炸锅要清洗了。

所以一次检查不是一次测量。它是一个决定,有时附带着一次测量。如果你在做一张油品 读数随时间变化的表,就要预料到有相当一部分行在值那一列里什么都没有,并且把它们 计入,而不是把它们丢掉——一个没有值的行动,仍然是一次确实发生过的检查。

拿它们做事

fryerEquipmentId 做连接。 一次检查只点出它的那台炸锅,别的什么都没有; 炸锅的名字在 fryer-equipment 上,那个你要单独遍历。两次遍历,在你这边做连接。

capturedAt 排序,而不是 receivedAt 一台平板会在找到信号时才上传,所以 一次 09:00 做的检查可能 14:00 才到。信封那一页讲了完整的来龙 去脉。

缺席证明不了什么。 一台这一周没有检查的炸锅,可能确实没被检查过,也可能正躺在 一台还没上传的设备里。不要把这类记录的计数变成一个合规数字——见 那条提醒

最后更新于 2026-09-20。