2017-04-22 36 views
0

我在Firebase中构建了一个应用程序,可以使用一些建议。以下是关键点:嘿#AskFirebase,我应该如何设计这个模式?

  • 该应用程序用于追踪员工工作的时间。
  • 用户分成团队,每个团队都有一个经理。
  • 随着用户进出时钟,应用会跟踪其工作时间。

我被困在设计问题上。这里是要求:

  • 经理可以读取&时间写卡上自己的球队的所有用户,而用户只能读取&自己写。
  • 当用户查看自己的时间卡时,UI需要显示按时间戳排序的最新时间卡。
  • 当经理正在查看其团队中每个人的时间卡时,UI需要显示按时间戳排序的最新时间卡。

同时解决所有3个要求被证明是一个挑战。我的第一直觉是构建时间卡这样的:

{ 
    "timeCards": { 
    "-teamId_1": { 
     "-userId_1": { 
     "-timeCard_1": { 
      "startsAt: 1234567890123, 
      "endsAt": 1234567899999, 
      "duration": 2234567 
     }, 
     "-timeCard_2": "..." 
     } 
    } 
    } 
} 

这解决了前两个要求很容易:

  • 容易写的权限规则,使得管理人员阅读了整个团队/写,但用户只能读/写他们自己的。
  • 便于查询按时间戳排序的特定用户的时间W/db.ref('timeCards/${tid}/${uid}').orderByChild('startsAt')

不幸的是,要解决这个模式的第三次要求,需要在客户端上一些繁重的。没有办法(我知道)通过时间戳排序查询所有团队时间卡的Firebase。所以,我不得不为队伍提供所有的时间卡,然后合并&在客户端进行排序。

我想这需要非规范化,也许这样的结构:

{ 
    "timeCards": { 
    "byTeam": { 
     "-teamId_1": { 
     "-timeCard_1": { 
      "userId": "-userId_1", 
      "startsAt: 1234567890123, 
      "endsAt": 1234567899999, 
      "duration": 2234567 
     }, 
     "-timeCard_2": "..." 
     } 
    }, 
    "byUser": { 
     "-userId_1": { 
     "-timeCard_1": { 
      "teamId": "-teamId_1", 
      "startsAt: 1234567890123, 
      "endsAt": 1234567899999, 
      "duration": 2234567 
     }, 
     "-timeCard_2": "..." 
     } 
    } 
    } 
} 

但这变得复杂的服务器上,需要两个火力地堡功能,一是看timeCards/byTeam和一个看timeCards/byUser,每个镜子记录导入其他集合。

虽然我不确定如何避免在这种情况下的无限更新循环。 (想象一下更新timeCards/byTeam/-teamId_1/-timeCard_1,它会触发Firebase功能并更新timeCards/byUser/...,从而触发Firebase功能并更新timeCards/byTeam/...等)

我是否缺少简单的解决方案?

回答

0

根据Firebase docs的最佳做法是尽可能保持数据平坦。因此,它可能看起来像这样:

{ 
    "users": { 
     "-userId_1": { 
      "name": "John" 
     }, 
     "-userId_2": { 
      "name": "Ann" 
     } 
    }, 
    "teams": { 
     "-teamId_1": { 
      "name": "Gladiators" 
     } 
    }, 
    "timeCards": { 
     "-timeCard_1": { 
      "startsAt": 1234567890123, 
      "endsAt": 1234567899999, 
      "duration": 2234567, 
      "userId": "-userId_1", 
      "teamId": "-teamId_1" 
     }, 
     "-timeCard_2": { 
      "startsAt": 1234567890123, 
      "endsAt": 1234567899999, 
      "duration": 2234567, 
      "userId": "-userId_2", 
      "teamId": "-teamId_1" 
     } 
    }, 
    "usersInTeams": { 
     "-teamId_1": { 
      "-userId_1": true, 
      "-userId_2": true 
     } 
    }, 
    "teamsInUsers": { 
     "-userId_1": { 
      "-teamId_1": true 
     }, 
     "-userId_2": { 
      "-teamId_1": true 
     } 
    }, 
    "timeCardsInUsers": { 
     "-userId_1": { 
      "-timeCard_1": true 
     }, 
     "-userId_2": { 
      "-timeCard_2": true 
     } 
    }, 
    "timeCardsInTeams": { 
     "-teamId_1": { 
      "-timeCard_1": true, 
      "-timeCard_2": true 
     } 
    } 
} 

然后,你可以写一个云功能,当你写为“考勤卡”触发(节点:/timeCards/{pushId}),并增加了考勤ID为“timeCardsInUsers”(节点:/timeCardsInUsers/{userId})和“ timeCardsInTeams“(节点:/timeCardsInTeams/{teamId})。

它应该解决循环问题,因为您写入不同的节点。