База данных Firebase Realtime - подписываться только на отдельные добавления, обновления, удаления - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть коллекция предметов в базе данных Firebase Realtime. Клиенты подписываются на изменения в пути к базе данных /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()
      })
    })
  }
}

I sh, чтобы сделать это более эффективным с точки зрения затрат сети, отправляя только обновленный элемент - при сохранении клиентских подписок.

Моя первоначальная мысль заключалась в том, чтобы реализовать подписку для каждого элемента:

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()
      })
    })
  }
}

Это выглядит немного громоздким, и обрабатывает только обновления и удаления. Он не обрабатывает случай дополнений, сделанных другим клиентом. Добавление должно происходить через отдельный узел базы данных *1014* (например, 'subscriptionAdditions //')? Кроме того, при начальной загрузке необходимо очистить все элементы в «subscriptionAdditions //», поскольку при первой загрузке все элементы считываются.

Опять камберы. : /

В заключение; Существует ли простой и / или рекомендуемый способ подписки на отдельные товары с учетом нескольких клиентов?

С уважением / K

1 Ответ

2 голосов
/ 06 апреля 2020

База данных Firebase Realtime синхронизирует состояние между структурой JSON на сервере и клиентами, которые наблюдают это состояние.

Кажется, вы хотите синхронизировать только часть этого состояния, насколько я можно увидеть в основном о последних изменениях в состоянии. В этом случае рассмотрите возможность моделирования самих изменений состояния в вашей базе данных.

Поскольку вы работаете с базами данных No SQL больше, вы увидите, что довольно часто модифицируют модель данных, чтобы разрешить каждый вариант использования. .


Например, если вам нужно только текущее состояние узлов, которые изменились, вы можете добавить свойство lastUpdated timestamp для каждого узла. Затем вы можете запросить только узлы обновлений с:

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

Если вы хотите прослушивать изменения с момента последнего подключения клиента, вам нужно сохранить временную метку, в которой они были где-то в последний раз, и используйте это вместо Date.now().


Если вы хотите синхронизировать все изменения состояния, даже если один и тот же узел менялся несколько раз, вам нужно будет хранить каждое изменение состояния в базе данных. Сохраняя их с хронологическими ключами (например, сгенерированными push()) или сохраняя временную метку для каждого, вы можете использовать тот же лог c, что и раньше, только для чтения изменения состояния, которое ваш клиент еще не обработал.


См. Также:

...