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



我在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//"中的所有项目,因为第一次加载读取所有项目。

再次,康伯斯通。:/

总之;有没有一种简单和/或推荐的方法可以在考虑多个客户的情况下实现订阅单个项目?

问候/K

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

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

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


例如,如果只需要已更改节点的当前状态,则可以为每个节点添加lastUpdated时间戳属性。然后,您可以使用以下内容仅查询更新节点:

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

如果要侦听自客户端上次联机以来的更改,则需要将它们上次联机的时间戳存储在某个位置,并使用该时间戳而不是Date.now()


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


另请参阅:

  • NoSQL数据建模
  • 如何只从Firebase获取新数据而不获取现有数据
  • 检索仅child从firebase添加到firebase中的侦听器

最新更新