【问题标题】:Query by child and key按子键和键查询
【发布时间】:2016-12-21 10:00:40
【问题描述】:

我想要达到的目标:

我有一个患者列表,不同的用户可以访问它们。因此我在 Firebase 中有这个结构

所有患者都在患者参考中。 所以基本上,我想检索与用户 UID 键匹配的患者。 理想情况下,我也会在读/写/详细信息部分过滤该数据,因为例如秘书将具有修改联系人数据的写入权限但无权访问详细信息,而学徒将具有完整的详细信息无修改权。

我所拥有的(不起作用):

var patientsRef = firebase.database().ref('patients').orderByChild('users').orderByKey().equalTo(uid);

还有一个问题:我在文档中找不到对我的问题的适当参考。我做错了什么?

【问题讨论】:

  • 你确定链接 orderBy 方法有效吗?
  • 不行,问题是你只能orderby一次!我想避免提取所有数据,但似乎我别无选择......!
  • 是的,看来你必须解决这个问题,github.com/firebase/angularfire/issues/652

标签: angularjs firebase firebase-realtime-database


【解决方案1】:

Firebase 通常不建议使用这种嵌套结构。它使查询几乎不可能(正如您所经历的那样),同时对患者数据应用任何访问控制。

请记住,查询需要对父节点的读取权限,如果授予权限,则永远不能隐藏任何子数据。


典型的解决方案是将这种患者-用户关系移动到单独的根节点。如果存在匹配关系 (ACL) 节点,则实际的患者数据只能逐个读取。

最好也“反转”关系:存储每个用户的患者,而不是每个患者的用户,以便您的应用程序可以直接将它们显示为列表。

提案:

/patients
    /PATIENTID1
        ... sensitive data
    /PATIENTID2
        ... sensitive data

/users
    /USERID1
        ...
    /USERID2
        ...

/user-patients
    /USERID1
        /PATIENTID1
            "name": "Patient name" (redundant copy for easy display)
            "detail": true,
            "write": false,
            ...

您的应用程序将加载 /user-patients 以显示当前用户可以访问的患者的个性化列表。安全规则也可以直接使用它(使用root 变量)来确保没有人读取或写入他们不应该读取或写入的内容。

【讨论】:

    【解决方案2】:

    编辑:阅读此答案的评论线程,了解为什么不应该这样做。请参阅 vzsgs 的答案。


    我建议在您的 json 中添加不同的部分,以便对其进行查询。 firebase 的要点之一是将数据结构化为易于查询,因此有时您必须复制数据。 (P.s.下次粘贴你的json)

    {
        "c237CV45SbhHfaRoicVyvFuy8e88" : {
            "firstName" : "Emeline",
            "gender": "f",
            "lastname": "Zagaroli",
            "users": {
                "p0R3CV45SBgGfaRoicVyvFuy8tq1": {
                    "detail": true,
                    "read": true,
                    "write": true
                }
            },
            "usersAssoc": {
                "p0R3CV45SBgGfaRoicVyvFuy8tq1": true
            }
        }
    }
    

    这样你就可以像这样写一个查询:

    var patientsRef = firebase.database().ref('patients').orderByChild('usersAssoc/p0R3CV45SBgGfaRoicVyvFuy8tq1').equalTo(true);
    

    【讨论】:

    • 不幸的是,这种方法存在严重的性能和安全问题。 1) 除非每个用户都添加到patients 节点的.indexOn 安全规则中——这实际上并不可行——否则此查询将下载所有内容并在客户端执行过滤。 2) 它要求/patients 可供所有人阅读。
    • 这不会下载所有内容,查询是在服务器上执行的,只返回真值。 orderBy 未在客户端执行。
    • 当且仅当设置了索引。这是服务器端过滤工作的先决条件。
    • 你说得对,我无法在文档中找到它,但在我创建测试时确实找到了它。对您的回答和 TIL 投了赞成票。
    • 我已经编辑了我的说他的更好。是的,请接受他的。
    猜你喜欢
    • 2022-01-02
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 2019-06-23
    • 2018-05-04
    相关资源
    最近更新 更多