【问题标题】:What Firebase rule will prevent duplicates in a collection based on other fields?什么 Firebase 规则将防止基于其他字段的集合中的重复?
【发布时间】:2013-12-14 03:47:15
【问题描述】:

我正在创建一个应用程序,它允许用户创建项目,然后允许其他用户订阅这些项目。我正在努力制定一条规则,以防止用户多次订阅一个项目。

这是我的数据结构的一个示例(匿名,因此是“OMITTED”值):

{
    "OMITTED" : {
        "name" : "Second",
        "body" : "this is another",
        "userName" : "Some User",
        "userId" : "OMITTED",
        "created" : 1385602708464,
        "subscribers" : {
            "OMITTED" : {
                "userName" : "Some User",
                "userId" : "OMITTED"
            }
        }
    }
}

这是我目前的 Firebase 规则:

{
  "rules": {
    ".read": true,
    ".write": "auth != null",
    "items": {
      "$item": {
        ".write": "!data.exists()",
        ".validate": "newData.hasChildren(['name', 'body', 'userId', 'userName']) && newData.child('userId').val() == auth.id",
        "subscribers": {
          "$sub": {
            ".validate": "newData.hasChildren(['userId', 'userName']) && newData.child('userId').val() != data.child('userId').val()"
          }
        }
      }
    }
  }
}

如何防止用户多次订阅?我需要什么规则来防止基于userId 的subscribers 列表中的重复用户?

【问题讨论】:

  • 如果您想防止多个条目具有相同的用户 ID,那么每个 ID 的记录都是唯一的。因此,使用用户 ID 作为该记录的键,那么只能有一个 :)
  • 为什么不把它作为一个实际的答案呢?
  • 因为时间是一种宝贵的商品,我的朋友,而且在我想花费的时间并不总是可用的。 :)

标签: validation firebase firebase-security


【解决方案1】:

由于安全规则无法迭代记录列表以找到包含特定数据位的记录,因此这里的技巧是通过允许轻松访问的 ID 存储记录。 denormalization 上有一篇很棒的文章,对这种做法提供了一些很好的见解。

在这种情况下,如果您的用例允许,您可能只想切换数据结构,以便通过用户的 ID 存储记录,而不是将 ID 作为值存储在记录中,如下所示:

/users/user_id/items/item_id/subscribers/user_id/

事实上,正如您将在非规范化中看到的那样,您甚至可以从更远的拆分中受益,具体取决于数据的确切大小以及您稍后将如何读取数据:

/users/user_id
/items/user_id/item_id
/subscribers/item_id/user_id

在这两种格式中,您现在可以通过以下方式很好地防止重复并锁定安全性:

{
   "users": {
      "$user_id": { ".write": "auth.id === $user_id" }
   },
   "subscribers": {
      "$subscriber_id": { ".write": "auth.id === $subscriber_id" }
   }
}

【讨论】:

  • 谢谢。这是我一直假设的,但想知道是否缺少某种 in 功能。
  • 这是一项要求的功能,我相信它最终会在某些时候出现在安全规则中!
  • 看来是这样。 in 对于任何类型的复合键规则都至关重要,除非他们期望每个应用程序都将复合键创建为主键。并非不合理,但考虑到 Firebase 可能的应用程序数量肯定不理想。
  • in() 操作的困难在于它们非常慢。因此,在像 Firebase 这样的实时 NoSQL 环境中,通常最好以允许您通过键引用数据的方式存储数据,或者在要搜索的字段上创建额外的索引。在写操作上做更多的工作以使读操作快如闪电,如果存在 in() 操作,我仍然更喜欢响应性索引。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 2017-03-06
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多