Я только вхожу в Firebase и до сих пор копаю его, но у меня возникла небольшая проблема с использованием функции Cloud для удаления элемента из массива в коллекции. В приложении, которое я использую, у пользователей есть документ в коллекции пользователей, который содержит пользовательские данные, которые не вписываются в модель аутентификации. Данные выглядят так:
Снимок экрана структуры пользовательской коллекции.
(Это приложение для фитнеса, поэтому массив называется «тренировки»)
Пользователь имеет возможность создать тренировку, и когда он это делает, после ее создания облачная функция, отслеживающая новые тренировки, добавляет идентификатор вновь созданной тренировки в пользовательский документ, добавляя его в массив тренировок с помощью arrayUnion. :
exports.addWorkoutToAuthorsListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onCreate((snap, context) => {
const id = context.params.workoutId
const name = snap.data().title
const uid = snap.data().author
const workout_reference = { id: id, name: name, uid: uid }
const workoutsRef = admin.firestore().collection("users").doc(uid)
return workoutsRef.update({
workouts: admin.firestore.FieldValue.arrayUnion(workout_reference)
})
})
Это работает нормально, но я хочу, чтобы пользователь мог удалять тренировки, и я не добавил строку в массив тренировок, а вместо этого объект, подобный этому:
{ id: "1214", name: "My workout", uid: "123asd" }
Теперь для этого точного варианта использования я мог бы удалить массив в своем приложении ReactJS, а затем выполнить обновление, но я собираюсь добавить возможность пользователям "нравится" тренировки других пользователей, что будет в результате ссылка на тренировку будет добавлена к "тренировкам" в их личном пользовательском документе. Поэтому, если я, как создатель тренировки, удаляю свою тренировку, мне нужно иметь возможность удалить ее из массива тренировок любого пользователя, у которого она есть. Использование arrayRemove не сработало, потому что (я полагаю) я не смог передать объект, который нужно удалить.
Каков наилучший способ сделать это? Я сделал эту попытку:
exports.removeWorkoutFromAuthorsListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onDelete((snap, context) => {
const id = context.params.workoutId
const uid = snap.data().author
const name = snap.data().name
let newWorkouts = new Array()
admin.firestore().collection("users").doc(uid).collection("workouts").get().then((querySnapshot) => {
querySnapshot.forEach((doc: any) => {
if (doc.id !== id) {
newWorkouts.push(doc.data())
}
});
});
const workoutsRef = admin.firestore().collection("users").doc(uid)
return workoutsRef.update({
workouts: newWorkouts
})
})
Но Firebase это совсем не понравилось, и я достаточно новичок в платформе, поэтому я понимаю, что это скорее всего из-за пробела в знаниях, а не из-за проблем с Firestore или Cloud Functions.
Буду очень признателен за любую помощь, которую вы сможете оказать. Ура!
ОБНОВЛЕНИЕ: Работает со следующим кодом:
exports.removeWorkoutFromSubscribersListOfWorkouts = functions.firestore
.document('workouts/{workoutId}')
.onDelete((snap, context) => {
const workoutId = context.params.workoutId
const subscribers = snap.data().subscribers
let newWorkouts = new Array()
subscribers.forEach(subscriber => {
let userRef = admin.firestore().collection("users").doc(subscriber)
return userRef.get().then(doc => {
return userRef.update({
workouts: doc.data().workouts.filter(workout => workout.id !== workoutId)
})
})
})
.catch(() => {
console.log("error")
})
})