使用Firebase对非规范化数据进行排序和过滤

时间:2016-05-26 08:43:30

标签: firebase firebase-realtime-database

我使用Firebase构建了一个包含两个模型的应用AB

  • AB之间存在一对多关系(A有许多B)。
  • AB需要易于查询,因此我需要一种方法来获取具有满足条件的属性的所有A模型。与B相同。
  • B有一个属性createdAt(永远不会更改)和一个属性status(它会不时更改)我希望列出所有Bs由特定A拥有,status和/或createdAt属性符合某些条件。
  • Bs是私有的,只能由经过身份验证的用户阅读,并且可以阅读他们所属的A(用户可以阅读b1,如果可以阅读a1 }和a1属于b1)。

关注Firebase guidelines,我的第一次尝试是做这样的事情:

"As": {
  "a1": {
    ...
    Bs: {
      "b1": true,
      ...
    },
  },
  ...
},
"Bs": {
  "b1": {
    ...,
    "status": "OPEN",
    "createdAt": 1464249410579,
  },
  ...
},

此解决方案的问题是,要访问属于Bs状态为a1且不超过一个月的OPEN,我必须访问a1.Bs ,获取所有ID,然后逐个访问Bs(这很好,根据Firebase guidelines)然后过滤它们以查明它们是否满足我的条件,我发现它非常低效的。

有关如何执行此操作的任何建议吗?

3 个答案:

答案 0 :(得分:1)

在思考了一下后,我们提出了这个解决方案:

"As": {
  "a1": {
    ...
    Bs: {
      "b1": { "status": "OPEN", "createdAt": 1464249410579 },
      ...
    },
  },
  ...
},
"Bs": {
  "b1": {
    ...,
    "status": "OPEN",
    "createdAt": 1464249410579,
  },
  ...
},

此解决方案允许我们保持数据库的结构平坦,以便数据AsBs可由例如管理员用户搜索和列出。它还尝试最小化数据重复,它可以用于我们希望包含在查询中的任意数量的属性。

要抓取属于Bs的{​​{1}}:

A

要抓取属于ref.child('as/:aId/bs').once('value') .then(snapshot => snapshot.forEach(...) // Access /bs/:bId where :bId = snapshotItem.key() Bs的{​​{1}},Astatus

OPEN

要抓取属于ref.child('as/:aId/bs') .orderByChild('status') .equalTo('OPEN') .once('value') .then(snapshot => snapshot.forEach(...) // Access /bs/:bId where :bId = snapshotItem.key() 的{​​{1}},Bs Astatus符合条件:

OPEN

在最后一种情况下,我们必须在客户端进行一些过滤,但这是由于Firebase的限制,我不认为我们可以避免它。无论如何,这是在id的数组上完成的,而不是在模型本身上完成的,它可能有20或30个属性,因此我们避免使用我们不需要的完整模型。

答案 1 :(得分:0)

我会做那样的事情:

 "As": {
  "a1": {
    ...
  },
  ...
},
"Bs": {
  "a1" : {
      "b1": {
        "status": "OPEN",
        "createdAt": 1464249410579,
      },
  },
},

a1是你的关键A

通过这种方式,您可以轻松查询属于bs

的所有a

这是我建议的here

答案 2 :(得分:0)

我会对此采取行动。

As
  a1
    Bs
      b1: true
      b2: true
  a2
    Bs
      b2: true
Bs
  b1:
    "open_a1": 1464249410579
  b2:
    "open_a1": 1464249410590
    "open_a2": 1464249410595

此结构允许您的代码从As节点知道链接到a1

的所有B

您可以查询Bs以查找所有open_a1<一个月

ref.queryByChild("open_a1").queryStaringAtValue(today)
                           .queryEndingAtValue(one month from today)

这是完全未经测试的,所以我可能需要修改解决方案。