Can't understand Firestore batch update - Flutter - firebase

What I understand after reading the Firestore official batch operations doc is that, Batch operations perform multiple operations and can change multiple documents simultaneously.
However, when I read the sample code in the official firestore doc for updates it says:
var sfRef = db.collection("cities").doc("SF");
batch.update(sfRef, {"population": 1000000});
Now, I don't understand why they gave the name of a specific document when trying to update the batch. I thought the whole point of batch operations was to update multiple documents in a collection, so why are we giving the name of the document and limiting the operation only to a single document.
Thanks in advance :)

Now, I don't understand why they gave the name of a specific document when trying to update the batch.
It's required to call out each individual document to create, update, or remove in the batch. There are no alternatives to this. Firesotre doesn't offer any way to bulk update multiple items as a result of a query, similar to SQL "update where" queries. If you have multiple items to update in a batch, you would instead have to:
Perform the query to find each document
Iterate the results and collect references to each document
Add each document update to the batch using the batch API.

Related

How to structure data Firestore, for multiple user enteries

This is my first time using a NOSQL database and I'm really struggling to work out how to structure my data.
I have an app that predicts a users mood and then the user can select if that's right or not. So I need to save both the prediction and the actual result. I want to be able to pull the latest result from firebase and display it on the app.
I understand how I'd do this on an SQL DB and understand how to write an SQL query to get that data back out.
For my Firebase DB I thought of the following structure
the document name is the usersID and store multiple arrays based on the timestamp but I can't seem to user OrderBy on a document only a collection so not sure how to get this back.
The fact that this seems so difficult less me to believe I've implemented the DB wrong to begin with.
Structure of DB is as follows:
I should add that it all works fine for the USER_TABLE as its one document id and a single entry, so I've no problem retrieving that.
Thanks for your help!
orderBy is an instruction to the database to order documents on the server, before it returns them to your app. To store the fields inside the document, you can just do that inside your application code after it receives the document(s).
There is in itself nothing wrong with storing these entries in a single document, Just keep in mind that:
A document can be at most be 1MB in size, so make sure this fits your maximum number of entries.
Firestore only ever returns full documents, so you will either get all entries in a document, or none of them.
You won't be able to order or filter the entries inside a single document. If that is a requirement for you, consider storing each entry in its own document in a subcollection. Note that this will increase the number of documents each user reads though, which will increase the cost.

Structuring a firestore database to filter by what is not in the array?

I have am building collection that will contain over a million documents. Each document will contain one token and a history table. A process retrieves a token, it stores the process id in the history table inside the document so it can never be used again by the same process. The tokens are reusable by different processes. I want to make each process pull a document/token and never be able to pull that same document/token again.
My approach is to have a stored history table in each document with the processes that have used the token. That is why you need to query for what is not in the array.
Firestore does not have a condition where you can search for what is not in an array. How would I perform a query like such below where array-does-not-contain being a placeholder to search through an array where 'process-001' is not in the history array?
db.collection('tokens').where('history', 'array-does-not-contain',
'process-001').limit(1).get();
Below is how I'm planning to structure my collection,
My actual problem,
I have a multiple processes running and I only want each process to pull documents from firebase that it's never seen before. The firebase collection will be over a million documents and growing.
Firestore is not very well suited for queries that need to look for things that don't exist. The problem is that the indexes it uses are only meant to tell you if things exist. The universe of strings that don't exist would be impossible to efficiently quantify for indexing.
The only want to make this happen is to know the names of all the processes ahead of time, and create values for them in the index. You would do this with a map type object, not an array:
- token: "1234"
- history: {
"process-001": false,
"process-002": false,
"process-003": false
}
This document can be queried to find out if "history.process-001" has a value of false, then updated to true when the process uses it. But again, without all the process names known ahead of time and populated in each document, the query is not possible.
See also:
Firestore get documents where value not in array?
How to query Cloud Firestore for non-existing keys of documents

Is it possible to do batched writes to add to existing fields?

My app has a for loop that writes data to my Firestore database.
However, right now, when I click my update button, Firestore updates the documents one by one, using transactions.
Thus, this results in me having to read every single document before being able to update it, which is extremely inefficient.
Is it possible for batched writes to perform an update feature similar to how transactions do?
For my case, the field I intend to update is a number, thus,
I am wondering if its possible to update the field by adding to it.
await transaction.update(stockListDocRef,
{'Num': outerStockListSnapshot.data['Num'] + Add});
You can use FieldValue.increment(x) to increment a field value in any sort of update operation, including batches.
See also: FieldValue.increment for Cloud Firestore in Flutter

Create a firestore document with a collection

I need to create a firestore doc which also has a collection, ideally in a single write operation.
I'm not seeing anything like this in the documentation, so failing that any tips on getting the created doc id and then adding multiple documents to a collection?
Edit: I'm developing in typescript/js
You can use a transaction or batch write to perform atomic operations among multiple documents. In both cases, you need to know all the IDs for all the documents you want to create ahead of time. You don't need to create a document in order for there to be a subcollection. Documents don't actually "contain" subcollection. Subcollections are currently just a technique for organizing your data.
It wasn't really clear from your question, but if your first document requires a generated ID, you can use the example code in the documentation that generates a DocumentReference object, which you can populate later in your transaction or batch.
Since you didn't say which language or system you're working on, I don't know which code sample to show here from the docs, so you'll have to go to the documentation linked here to see how it works. You'll end up using a method called "doc" or "document" on a CollectionReference to generate the DocumentReference with the generated ID.

Create multiple documents in Cloud Firestore at the same time

Is it possible to create multiple documents against a collection using Cloud Firestore in the same transaction?
I'm looking at the documentation on batched writes. Unless I'm mistaken (I'm new to Firebase, so could be the case) these examples are meant to demonstrate 'batched writes' but the examples only show a single field being updated.
Yes. Batched writes can work for both updating a single field on multiple documents, or creating a bunch of documents at once.
Follow this link to see a similar case i had which i solved. It talked about a collection with its documents being automatically created when a document is created. You will get an idea on how to solve your issue from it.
The link is thus: When collection is created, the documents are added to it at once
I hope it helps.

Resources