Firestore нежелательное сохранение повторных записей - PullRequest
0 голосов
/ 15 марта 2020

Я пытаюсь сохранить места рядом со мной для теста. Я запустил следующий код:

var macro_query = db.collection("cafes");
    macro_query = macro_query.where("name", "==", place.name); // check whether name exists
    console.log("Checking final query: ", macro_query); // check whether it exists
    macro_query.get()
      .then(function(querySnapshot) {
        console.log(querySnapshot.empty); // returns true if empty, returns false if place.name is already in database

        if (querySnapshot.empty) {
          db.collection("cafes").add({ // store it since it doesnt exist
            name: place.name,
          });
          console.log("Added into database: ", place.name);
        } else {
          console.log("Location already in database");
        }
      });

Лог c кода в основном для проверки базы данных, если place.name уже существует. Если это так, скрипт ничего не делает, в противном случае место должно быть добавлено в базу данных.

Код работает хорошо после нескольких тестов, чтобы убедиться, что он никогда не добавляет одно и то же местоположение дважды. Но после многократного запуска я заметил, что в моем хранилище может быть более 2 уникальных ключей с одним и тем же местоположением (то есть 3 местоположения с одинаковым именем)

Мой код где-то не работает, и я я не соответствую правильно?

Примечание, мне интересно, это из-за моих правил безопасности?

// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

1 Ответ

0 голосов
/ 15 марта 2020

Это не имеет ничего общего с правилами безопасности.

Ваш код имеет состояние гонки. Поскольку между запросом и обновлением существует небольшой промежуток времени, это означает, что вы можете получить несколько параллельных запросов, каждый из которых будет добавлять магазин с одинаковым именем. К сожалению, для веб-клиентов и мобильных клиентов Firestore нет способа выполнить такой запрос атома c, чтобы избежать условия гонки. Транзакции Firestore здесь вам не помогут, так как вы не можете выполнить запрос внутри транзакции.

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

  1. Имена ваших магазинов также являются действительными идентификаторами документов
  2. Или у вас есть выделенная коллекция для хранения закодированных имен магазинов в качестве идентификаторов документов с параллельными документами в другой коллекции, которая на самом деле содержит данные хранилища.

Если вы выберете # 2, вам придется потрудиться, чтобы это произошло гладко.

...