1
votes

I have several fields in one document that contain user records for mini games. After the user has played a few of them, I update the records in this document. I cannot be allowed to overwrite the existing record value with a smaller one. Therefore, I need to maximize them.

The solutions I have considered:

  1. Transactions. This solution does not work for me, because it will not work without an Internet connection.
  2. Cloud Functions. I can trigger the function when the document is updated or created. This solution works for me, but it complicates the logic in my application a lot.
  3. Security Rules. I can prevent the document from being written if its new value is less than the old one. But this solution will only work well if you write one field at a time.

Ideally, I would like something like the following:

let data: [String: Any] = [
    "game_id0": FieldValue.maximum(newRecord0),
    "game_id1": FieldValue.maximum(newRecord1),
    "game_id2": FieldValue.maximum(newRecord2),
]
let docRef = db.collection("user_records").document(documentId)
docRef.setData(data, merge: true)

But unfortunately FieldValue class only has methods: increment, arrayUnion, arrayRemove and delete. In the description for the protocol, I found the maximum and minimum methods, but I doubt that this can be legally used.

Can anyone tell me any other feasible method?

UPD:

Let the following document be stored on the server:

{ "game_id": 13 }

The user plays the game from one device (which is offline) and scores 20 points.

Then the same user plays the same game from another device (which is online) and scores 22 points. An update request is sent. The server now stores the following information:

{ "game_id": 22 }

On the first device of the user, the Internet appears and the recording takes place. In this case, overwriting occurs and the document takes the following form:

{ "game_id": 20 }

That is, the previously collected user record is overwritten. But I need the recording to occur only if the new value is greater than the current one. That is, the data after step two should not change.

1
Can you clarify the firestore model? Does the user all share a single document or each user has it's own document and multiple games stats inside those? - Hugo Gresse
@HugoGresse Each user has his own document that contains records for several mini-games. As a result, the document contains about 20 fields. - dronpop
what are the fields values? Isn't increment enough? - Hugo Gresse
@HugoGresse I have added an example. Look please. - dronpop
I'll probably go to store each new entry in separate document and aggregate it at runtime, thus making the game_id either at runtime, or with a cloud functions that will aggregate the id and put it in another field. - Hugo Gresse

1 Answers

1
votes

If you can't use a transaction (which would normally be the right thing to do), then you have to use one of your other methods. I don't think you have any alternatives. You are probably going to have an easier time with Cloud Functions, and I don't think that's going to complicate things as much as you say. It should just be a few lines of code to check that any updated value should not be less than existing values.