Можно ли обновить firestore, используя предыдущее состояние?
Так, например, у меня есть адресный документ, в котором есть поле users
которое содержит массив пользователей, связанных с адресом. когда я хочу добавить нового пользователя в этот массив, мне нужен предыдущий массив, иначе я закончу переписывание текущих данных новыми данными.
Поэтому я получаю что-то вроде этого.
firestore()
.collection("addresses")
.doc(addressId)
.get()
.then(doc => {
this.db
.collection("addresses")
.doc(addressId)
.update({
users: [...doc.data().users, id]
})
});
Есть ли способ получить доступ к предыдущим данным без необходимости вложенных вызовов?
если не
Есть ли лучший способ управлять отношениями?
Если для определения нового значения требуется предыдущее значение, вы должны использовать транзакцию. Это единственный способ гарантировать, что разные клиенты не случайно перезаписывают друг друга.
К сожалению, транзакции также нуждаются в вложенных вызовах, поскольку это единственный способ получить текущее значение и даже иметь одну дополнительную оболочку (для транзакции.
var docRef = firestore()
.collection("addresses")
.doc(addressId);
return db.runTransaction(function(transaction) {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(docRef).then(function(doc) {
transaction.update(docRef, { users: [...doc.data().users, id ]});
});
}).then(function() {
console.log("Transaction successfully committed!");
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
Оптимальным решением является использование структуры данных, которая не требует, чтобы текущее значение добавляло новые значения. Это одна из причин, почему Firebase рекомендует не использовать массивы: они по своей сути трудно масштабировать, когда несколько пользователей могут добавлять элементы в массив. Если нет необходимости поддерживать порядок между пользователями, я бы рекомендовал использовать подобную структуру для пользователей:
users: {
id1: true,
id2: true
}
Это коллекция с двумя пользователями (id1
и id2
). true
значения - это только маркеры, поскольку у вас не может быть поля без значения.
С этой структурой добавление пользователя так же просто, как:
firestore()
.collection("addresses")
.doc(addressId)
.update({ "users.id3": true })
Также см. Документацию Firestore по работе с массивами, списками и наборами