Поиск и обновление транзакций в базе данных Firebase - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть коллекция в базе данных реального времени firebase, которая представляет собой пул кодов, которые можно использовать один раз для «магазина».Мне нужно найти неиспользуемый код, а затем пометить его как зарезервированный в магазине.Проблема в том, что я не могу понять, как выполнять поиск и обновление транзакций в firebase, и неиспользуемый код «используется» несколько раз, пока не будет обновлен.

const getUnusedCode = (storeID) => {
  const codeRef = rtdb.ref('codes');

 return codeRef
    .orderByChild(storeID)
    .equalTo(null)
    .limitToFirst(1)
    .once('child_added')
    .then(snap => {
     //setting the map {[storeID]:true} reserves the code
     return snap.ref.update({ [storeID]: true }).then(() => {
        return snap.key;
      });
    });
};

Редактировать: ВотСтруктура коллекции «Коды»:

{
  "-LQl9FFD39PAeN5DnrGE" : {
    "code" : 689343821901,
    "i" : 0,
    "5s6EgdItKW7pBIawgulg":true,
    "ZK0lFbDnXcWJ6Gblg0tV":true,
    "uKbwxPbZu2fJlsn998vm":true
  },
  "-LQl9FOxT4eq6EbwrwOx" : {
    "code" : 689343821918,
    "i" : 1,
    "5s6EgdItKW7pBIawgulg":true
  },
  "-LQl9FPaUV33fvkiFtv-" : {
    "code" : 689343821925,
    "i" : 2
  },
  "-LQl9FQEwKKO9T0z4LIP" : {
    "code" : 689343821932,
    "i" : 3,
    "ZK0lFbDnXcWJ6Gblg0tV":true
  },
  "-LQl9FQsEVSNZyhgdHmI" : {
    "code" : 689343821949,
    "i" : 4,
    "5s6EgdItKW7pBIawgulg":true,
    "uKbwxPbZu2fJlsn998vm":true
  }
}

В этих данных «5s6EgdItKW7pBIawgulg» является идентификатором магазина, и «истина» означает, что этот код был использован для этого магазина

Когда новые элементыбудучи импортированной, эта функция может вызываться hundres раз в минуту и ​​возвращает дубликаты, поскольку это не атомарный поиск, а затем обновление.Возможно ли это в Firebase?

1 Ответ

0 голосов
/ 01 декабря 2018

Из того, что я понимаю, у вас есть такая структура

codes: {
  "code1": {
    storeid: "store1"
  },
  "code2": {
    storeid: "store2"
  }
}

И вы пытаетесь обновить ее транзакционно для каждого магазина.

Если это единственное обновление, которое вы пытаетесь сделать, я настоятельно рекомендую инвертировать вашу структуру данных:

codes: {
  "store1": "code1",
  "store2": "code2"
}

В этой структуре транзакция для магазина довольно проста,поскольку путь известен:

var storeRef = firebase.database().ref("codes").child("store1");
storeRef.transation(function(current) {
  if (current) {
    // remove the code from the database
    return null;
  }
  else {
    // abort the transaction, since the code no longer exists
    return undefined;
  }
});

Если вы не можете изменить структуру данных, я бы, вероятно, использовал ваш текущий код, чтобы найти код DatabaseReference, а затем использовал бы транзакцию внутриобратный вызов для обновления:

codeRef
    .orderByChild(storeID)
    .equalTo(null)
    .limitToFirst(1)
    .once('child_added')
    .then(snap => {
      //setting the map {[storeID]:true} reserves the code
      return snap.ref.transaction(function(current) {
        if (!current || current[storeId]) {
          // the node no longer exists, or it already was claimed for this store
          return undefined; // abort the transaction
        }
        else {
          current[storeId] = true;
          return current;
        }
      })
    });
...