I have a scheduled function that resets an integer value back to zero in my firestore. The problem that I'm running into is that, while the merge-set succeeds (for the specified properties), it somehow resets my Organization document reference to null.
So far I've tried the following
Update() function (instead of Set()). While this works, it is untyped, and I have to get rid of the converter which encapsulates the moment() to Date conversion.Set() and simply pass the entire object. user.reference?.withConverter(userConverter).set(user)
This is also working but it overrides the entire user object and can lead to concurrency issues in case a user also updates his object while the timed function is running.
I'm looking for a solution that allows me to use the converter class along with a merge Set().
The User interface looks like this
export interface User extends Document {
email?: string
name?: string
organization?: Organization | null
numberOfForwards?: number
lastForwardReset?: moment.Moment
}
with its converter like so
export class UserConverter implements firestore.FirestoreDataConverter<User> {
toFirestore(user: User): firestore.DocumentData {
return {
email: user.email,
name: user.name,
organization: user.organization ? user.organization.reference : null,
number_of_forwards: user.numberOfForwards,
last_forward_reset: user.lastForwardReset?.toDate()
}
}
fromFirestore(snapshot: firestore.QueryDocumentSnapshot): User {
const data = snapshot.data()!
return {
reference: snapshot.ref,
email: data.email,
name: data.name,
organization: data.organization ? { reference: data.organization } : null,
numberOfForwards: data.number_of_forwards,
lastForwardReset: moment(data.last_forward_reset.toDate())
}
}
}
export const resetNumberOfForwards = functions.pubsub
.schedule('every 15 minutes')
.onRun(async () => {
const reset = (user: User) => {
console.log(`Resetting ${user.email} from [${user.numberOfForwards}] to [0]`)
// Claim user reference
user.reference
?.withConverter(userConverter)
.set({ numberOfForwards: 0, lastForwardReset: Moment() }, { merge: true })
}
for the partial set to work, I've included the following snippet on top of my file
firebase.firestore().settings({
ignoreUndefinedProperties: true
})