Firebase数据twitter克隆的结构

时间:2015-08-01 12:40:10

标签: firebase

我正在尝试创建一个推文克隆以学习使用Firebase,我很想得到关于如何创建数据库结构的建议。我最关心的是关注关注者以及如何在关注500个用户时创建时间表。您需要执行500个查询并以某种方式对日期时间进行排序。

{
  "followers" : {
    "cesar" : {
      "followers" : {
        "cesar2" : true
      },
      "following" : {
        "cesar2" : true
      }
    },
    "cesar2" : {
      "followers" : {
        "cesar" : true
      },
      "following" : {
        "cesar" : true
      }
    }
  },
  "tweet" : {
    "cesar" : [ null, {
      "content" : "tweet 1"
    } ]
  },
  "users" : {
    "cesar" : {
      "name" : "César",
      "notifications" : true,
      "username" : "cesar"
    },
    "cesar2" : {
      "name" : "César2",
      "notifications" : false,
      "username" : "cesar2"
    }
  }
}

1 个答案:

答案 0 :(得分:9)

请参阅Firebase的开源Twitter克隆Firefeed。它包含它使用的walkthrough数据结构,归结为在发布新消息时使用扇出方法。以下是使用的规则的副本,它描述了基础数据结构:

{
  "rules": {
    // All data is readable by anyone.
    ".read": true,
    "people": {
      // A list of users with their names on the site.
      "$userid": {
        // Only the user can write their own entry into this list.
        ".write": "$userid ==auth.uid"
      }
    },
    "users": {
      "$userid": {
        // The user is allowed to write everything in their bucket.
        ".write": "$userid ==auth.uid",
        "following": {
          // The following list should only contain actual ids from the "people" list.
          "$followingid": {
            ".validate": "root.child('people').hasChild($followingid)"
          }
        },
        "followers": {
          // Anyone can add themself to to this user's followers list.
          "$followerid": {
            ".write": "$followerid ==auth.uid"
          }
        },
        "feed": {
          "$sparkid": {
            // User A can write in user B's feed, but only if A is following B, and only for sparks for which they are the author.
            ".write": "root.child('users/' + $userid + '/following').hasChild(auth.uid) && root.child('sparks/' + $sparkid + '/author').val() ==auth.uid"
          }
        }
      }
    },
    "sparks": {
      // A global list of sparks (the "firehose").
      "$sparkid": {
        // Modifying an existing spark is not allowed.
        ".write": "!data.exists()",
        // Every spark should have an author and a body.
        ".validate": "newData.hasChildren(['author', 'content'])",
        // A user can attribute a spark only to themselves.
        "author": {
          ".validate": "newData.val() ==auth.uid"
        },
        "content": {
          ".validate": "newData.isString()"
        }
      }
    },
    "recent-users": {
      // Users can add themselves to the list of users with recent activity.
      "$userid": {
        ".write": "$userid ==auth.uid"
      }
    },
    "recent-sparks": {
      // Authors of sparks can add their sparks to this list.
      "$sparkid": {
        ".write": "root.child('sparks/' + $sparkid + '/author').val() ==auth.uid"
      }
    },
    "search": {
      "firstName": {
        "$searchKey": {
          ".write": "auth != null && (root.child('people/' +auth.uid + '/firstName').val() + '|' + root.child('people/' +auth.uid + '/lastName').val() + '|' +auth.uid) == $searchKey && newData.val() ==auth.uid"
        }
      },
      "lastName": {
        "$searchKey": {
          ".write": "auth != null && (root.child('people/' +auth.uid + '/lastName').val() + '|' + root.child('people/' +auth.uid + '/firstName').val() + '|' +auth.uid) == $searchKey && newData.val() ==auth.uid"
        }
      }
    }
  }
}