在firebase中,使用单独的端点模拟许多许多关系是一个好主意? [英] In firebase, is modeling many-many relationships using a separate endpoint a good idea?

查看:112
本文介绍了在firebase中,使用单独的端点模拟许多许多关系是一个好主意?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个典型的用户&分组数据模型,其中用户可以在多个组中,并且组可以有许多用户。在我看来, Firebase文档建议我塑造我的通过在用户组内复制用户标识符和用户内部组标识符来获取数据,如下所示:

  {
usergroups:{
bob:{
groups:{
one:true,
two:true
}
},
fred:{
groups:{
one:true
}
}
},
groupusers:{
one:{
users:{
bob:true,
fred:true
}
},
two:{
users:{
bob:true
}
}
}
}
<为了保持这种结构,每当我的应用程序更新关系的一侧(例如,将用户添加到组)时,还需要更新关系的另一方(例如,将该组添加到用户) 。

我担心最终某个人的电脑会在更新的过程中崩溃,否则就会出错,双方的关系会不同步。理想情况下,我想把更新放在一个事务中,以便双方都得到更新,或者双方都不做,但据我所知,我不能用firebase中当前的事务支持来做到这一点。

b
$ b

另一种方法是使用即将到来的firebase触发器来更新关系的另一端,但触发器尚不可用,它似乎是一个相当重量级的解决方案,将消息发布到外部服务器只是让该服务器保持冗余数据最新。



因此,我正在考虑另一种方法,即将许多用户组成员资格存储为单独的端点:$ b​​
$ b

  {
会员资格:{
id1:{
user:bob,
group :one
},
id2:{
user:bob,
group:two
},
id3:{
user:fred,
group:one
}
}
}

我可以在user和group上添加索引,并发出firebase查询.orderByChild(user) .equalTo(...)和.orderByChild(group)。equalTo(...)分别确定特定用户的组和用户。

这种方法有什么缺点?我们不再需要维护多余的数据,为什么这不是推荐的方法呢?它是否比推荐的复制数据方法慢得多?

解决方案

在设计中,您总是需要访问三个位置来显示用户和她的组:


  1. 用户孩子确定用户的属性
  2. $ 用于确定她是哪个组的成员c> child来确定组的属性

在文档的非规范化示例中,您的代码只需要访问#1和#3,因为会员信息嵌入用户组。



如果您进一步规范化,您最终将为每个用户存储所有相关的组信息,并为每个组存储所有相关的用户信息。有了这样的数据结构,您只需要读取一个位置来显示组或用户的所有信息。



冗余不一定是坏事一个NoSQL数据库,实际上正是因为它加快了速度。



目前,我将与辅助进程一起定期扫描数据,并协调所发现的任何不规则数据。当然,这也意味着常规的客户端代码需要足够强大,以处理这种不规则的数据(例如,一个指向用户的组,这个用户的记录不指向该组)。

或者,您可以设置一些高级的 .validate 规则,以确保双方始终保持同步。我只是总是发现需要更多的时间来实现,所以从来没有打扰。

您可能也想阅读这个答案: Firebase数据结构和url

Suppose I have a typical users & groups data model where a user can be in many groups and a group can have many users. It seems to me that the firebase docs recommend that I model my data by replicating user ids inside groups and group ids inside users like this:

{
  "usergroups": {
    "bob": {
      "groups": {
        "one": true,
        "two": true
       }
    },
    "fred": {
      "groups": {
        "one": true
      }
    }
  },
  "groupusers": {
    "one": {
      "users": {
        "bob": true,
        "fred": true
      }
    },
    "two": {
      "users": {
        "bob": true
      }
    }
  }
}

In order to maintain this structure, whenever my app updates one side of the relationship (e.g., adds a user to a group), it also needs to update the other side of the relationship (e.g., add the group to the user).

I'm concerned that eventually someone's computer will crash in the middle of an update or something else will go wrong and the two sides of the relationship will get out of sync. Ideally I'd like to put the updates inside a transaction so that either both sides get updated or neither side does, but as far as I can tell I can't do that with the current transaction support in firebase.

Another approach would be to use the upcoming firebase triggers to update the other side of the relationship, but triggers are not available yet and it seems like a pretty heavyweight solution to post a message to an external server just to have that server keep redundant data up to date.

So I'm thinking about another approach where the many-many user-group memberships are stored as a separate endpoint:

{
  "memberships": {
    "id1": {
      "user": "bob",
      "group": "one"
    },
    "id2": {
      "user": "bob",
      "group": "two"
    },
    "id3": {
      "user": "fred",
      "group": "one"
    }
  }
}      

I can add indexes on "user" and "group", and issue firebase queries ".orderByChild("user").equalTo(...)" and ".orderByChild("group").equalTo(...)" to determine the groups for a particular user and the users for a particular group respectively.

What are the downsides to this approach? We no longer have to maintain redundant data, so why is this not the recommended approach? Is it significantly slower than the recommended replicate-the-data approach?

解决方案

In the design you propose you'd always need to access three locations to show a user and her groups:

  1. the users child to determine the properties of the user
  2. the memberships to determine what groups she's a member of
  3. the groups child to determine the properties of the group

In the denormalized example from the documentation, your code would only need to access #1 and #3, since the membership information is embedded into both users and groups.

If you denormalize one step further, you'd end up storing all relevant group information for each user and all relevant user information for each group. With such a data structure, you'd only need to read a single location to show all information for a group or a user.

Redundancy is not necessarily a bad thing in a NoSQL database, indeed precisely because it speeds things up.

For the moment I would go with a secondary process that periodically scans the data and reconciles any irregular data it finds. Of course that also means that regular client code needs to be robust enough to handle such irregular data (e.g. a group that points to a user, where that user's record doesn't point to the group).

Alternatively you could set up some advanced .validate rules that ensure the two sides are always in sync. I've just always found that takes more time to implement, so never bothered.

You might also want to read this answer: Firebase data structure and url

这篇关于在firebase中,使用单独的端点模拟许多许多关系是一个好主意?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆