firebase - Firebase Realtime DB:按键的值数量对查询结果进行排序
问题描述
我有一个带有用户的 Firebase Web Realtime DB,每个用户都有一个jobs
属性,其值是一个对象:
{
userid1:
jobs:
guid1: {},
guid2: {},
userid2:
jobs:
guid1: {},
guid2: {},
}
我想查询以获得最多工作的 n 个用户。我可以使用 orderby 技巧按给定用户在其jobs
属性中具有的值的数量对用户进行排序吗?
我特别不想存储每个用户拥有的作业数量的整数计数,因为我需要更新用户的jobs
属性作为同时原子更新其他用户属性的原子更新的一部分,而且我不相信事务(像递增/递减计数器)可以成为这些原子事务的一部分。
这是我正在做的那种原子更新的例子。请注意,当我运行以下更新时,我在内存中没有我正在修改的用户:
firebase.database().ref('/').update({
[`/users/${user.guid}/pizza`]: true,
[`/users/${user.guid}/jobs/${job.guid}/scheduled`]: true,
})
非常感谢任何有关适用于这些数据的模式的建议!
解决方案
实时数据库事务在 JSON 树中的单个节点上运行,因此很难将jobCounter
原子更新中的节点更新集成到多个节点(即 to /users/${user.guid}/pizza
和/users/${user.guid}/jobs/${job.guid}/scheduled
)。我们需要更新/users/${user.guid}
级别并计算计数器值等...
一种更简单的方法是使用云函数来更新用户的jobCounter
节点,每次有一个jobs
节点发生变化,这意味着计数器的变化。换句话说,如果添加或删除了新的作业节点,则更新计数器。如果仅修改现有节点,则不会更新计数器,因为作业数量没有变化。
exports.updateJobsCounter = functions.database.ref('/users/{userId}/jobs')
.onWrite((change, context) => {
if (!change.after.exists()) {
//This is the case when no more jobs exist for this user
const userJobsCounterRef = change.before.ref.parent.child('jobsCounter');
return userJobsCounterRef.transaction(() => {
return 0;
});
} else {
if (!change.before.val()) {
//This is the case when the first job is created
const userJobsCounterRef = change.before.ref.parent.child('jobsCounter');
return userJobsCounterRef.transaction(() => {
return 1;
});
} else {
const valObjBefore = change.before.val();
const valObjAfter = change.after.val();
const nbrJobsBefore = Object.keys(valObjBefore).length;
const nbrJobsAfter = Object.keys(valObjAfter).length;
if (nbrJobsBefore !== nbrJobsAfter) {
//We update the jobsCounter node
const userJobsCounterRef = change.after.ref.parent.child('jobsCounter');
return userJobsCounterRef.transaction(() => {
return nbrJobsAfter;
});
} else {
//No need to update the jobsCounter node
return null;
}
}
}
});
推荐阅读
- twilio - 如何从 Twilio Studio 创建一个 http 请求
- stored-procedures - 使用存储过程透视表
- tfs - 是否可以从 TFS(或 Azure DevOps)导出/导入板配置
- grep - 显示不以一个或多个字母开头且不以一个或多个数字结尾的行
- node.js - 导出带有添加方法的模块返回对象
- reactjs - useEffect 更新后的本地状态行为
- arduino - 如何使用 Arduino Uno 在不同状态之间切换?
- python - 按索引访问 Python 列表
- mysql - 在 MySql 中将随机数据插入到表中
- mysql - 尽管没有冲突,但 MySQL 列权限会覆盖全局权限