Firebase 实时数据库 - 仅订阅单个添加、更新、删除

Firebase Realtime database - only subscribe to single adds, updates, deletes

我在 Firebase 实时数据库中有一组项目。客户端订阅数据库 /items 路径中的修改。但这具有每次添加、更新或删除单个项目时将所有项目发送给客户端的效果。这可能是多达 1000 个项目被发送到客户端,仅仅因为一个项目文本被更新为 一个 个字符。

此代码有效,但不符合我的要求:

export const startSubscribeItems = () => {
  return (dispatch, getState) => {
    return new Promise(resolve => {
      database.ref('items')
      .orderByChild(`members/${uid}`)
      .equalTo(true)
      .on('value', (snapshot) => {
        let items = []
        snapshot.forEach( (childSnap) => {
          const id = childSnap.key
          const item = {id, ...childSnap.val()}
          items.push(item)
        })
        dispatch(setItems(items))
        resolve()
      })
    })
  }
}

我希望通过仅发送已更新的项目来提高网络成本效益 - 同时保持客户订阅。

我最初的想法是为每个项目实现订阅:

export const startSubscribeSingleItems = () => {
  return (dispatch, getState) => {
    return new Promise(resolve => {
      database.ref('items')
      .orderByChild(`access/members/${uid}`)
      .equalTo(true)
      .once('value', (snapshot) => {
        let items = []
        snapshot.forEach( (childSnap) => {
          const id = childSnap.key
          const item = {id, ...childSnap.val()}
          items.push(item)
          // .:: Subscribe to single item node ::.
          database.ref(`items/${id}`).on('value', (snap)=>{
             // Some logic here to handle updates and deletes (remove subscription)
          })
        })
        dispatch(setItems(items))
        resolve()
      })
    })
  }
}

这似乎有点笨重,而且只处理更新和删除。它不处理其他客户添加的情况。必须通过 单独的 数据库节点(例如 'subscriptionAdditions//')进行添加?此外 - 初始加载必须清除 "subscriptionAdditions//" 中的所有项目,因为第一次加载会读取所有项目。

再一次,坎伯斯通。 :/

总而言之;有没有一个简单的and/or推荐的方法来实现订阅单个项目同时考虑到多个客户?

亲切的问候/K

Firebase 实时数据库在服务器上的 JSON 结构与观察该状态的客户端之间同步状态。

据我所知,您似乎只想同步该状态的一个子集,主要是关于最近对该状态的更改。在这种情况下,请考虑对数据库中的状态变化本身进行建模。

随着您更多地使用 NoSQL 数据库,您会发现修改数据模型以允许每个用例是很常见的。


例如,如果你只需要当前发生变化的节点的状态,你可以给每个节点添加一个lastUpdated时间戳属性。然后你可以只查询更新节点:

database.ref('items')
  .orderByChild('lastUpdated')
  .startAt(Date.now())

如果您想监听客户端上次在线后的变化,您需要将他们上次在线的时间戳存储在某个地方,并使用它代替 Date.now()


如果你想同步所有的状态变化,即使同一个节点被多次改变,你也需要在数据库中存储每个状态变化。通过保留那些按时间顺序排列的键(例如由 push() 生成的键)或为每个键存储一个时间戳,然后您可以使用与以前相同的逻辑来仅读取您的客户端尚未处理的状态更改。


另见: