Using firebase .update within a .where (instead of .doc) - javascript

I am new to firebase and am struggling a little bit.
Currently, I am trying to update an array within a user, within a document. However, I cannot match the user to current user using the unique ID, as each users unique ID is their username, and it may have changed since creation.
I figured the best way to match the documents user to the current user would be to use a .where().get() and then use an "update()" to update the array.
Now, this is where I am getting stuck. In the firebase documents, their example of using .update is attached to a .doc
var washingtonRef = db.collection("cities").doc("DC");
//Atomically add a new region to the "regions" array field.
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});
However, as I am using a .where, I assume I have to use references and snapshots. But, I am not quite sure how references work in this scenario and, with that, how to update properly.
Here is the code I have after a while of messing round, but no matter my variations i cannot figure it out. (essentially, I want to add a new project (in this case called "new project" to the users array of postedProjects.)
db.collection('users').where('user_id', '==', this.userInfo.user_id)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
doc.data().update({
postedProjects: firebase.firestore.FieldValue.arrayUnion("new project")
})
})
})
This gives me an error of ".update() is not a function".
Is anyone able to help me with my solution to show me how references should properly be used in this scenario?

You're almost there. You can't update the data of DocumentSnapshot though, since that is the in-memory representation of the document data. Instead you need to get the DocumentReference and call update on that.
doc.ref.update({
postedProjects: firebase.firestore.FieldValue.arrayUnion("new project")
})

You need a DocumentReference in order to update() a document. Nothing else will work.
In your code, doc is a QueryDocumentSnapshot type object. If you want the DocumentReference object that refers to the document from that snapshot, use its ref property.
doc.ref.update({
postedProjects: firebase.firestore.FieldValue.arrayUnion("new project")
})

Related

Firebase - Create subcollection only if the parent doc exists

In Firestore, when you are deleting a doc, you can specify a condition like { exists: true }, in order to avoid deleting the document if it doesn't exist.
In a concurrent scenario, it is possible that we would only like to add a doc to a subcollection if the parent document exists.
For example, imagine the following NoSql structure:
-comment (doc)
/likes (subcollection created when the first like is given)
-like1
-like2
...
Is it possible to do something like
likeRef.create(data, { parent_exists: true });
??
Is the only way to handle this situation with Transactions (reading the parent doc, and throwing an error when .exists() is false)?
I am afraid of this type of situation because if the sub-collection is created at the same time as the container document is deleted, there could be orphan "entities" in the database that may even break the UI if it is not prepared for these extreme cases.
This is not possible as a single operation in Firestore.
The only way to do this is to start a transaction, then get() the parent document inside the transaction, and add the documents to the subcollection if the parent exists.

Remove all fields associated linked to a document that I removed on another collection

For the context I'm using firebase/nodeJS on my application.
I'm deleting an user of a collection called workers. To do so I update the field deleted : true on the worker document.
I'm not deleting the document, because I want to keep their infos if needed.
But when I delete a worker, I must remove him from all the properties is working on (they have a field called workers, which is an array of all the workers associated.)
Hence, I must browse all the properties of the collection associated, check if the worker is on it and remove him.
Is there a way to do so ?
I saw this page : https://firebase.google.com/docs/firestore/manage-data/add-data#node.js_11
But don't know how to use theses ressources to do so.
So I finally did it alone.
First, I had to fetch all the properties where the work is working on, to do this I used array-contains.
let docsProperties = await db.collection('user').doc(id).collection("properties")
.where("workers", "array-contains", workerId).get();
Then I wanted to browse all theses properties and remove the worker. Thought about doing a ForEach first. But the problem is I wanted to use an await .update() with arrayRemove and async methods aren't usable inside ForEach.
So I used promises.
let promises = [];
docsProperties.forEach(doc => {
promises.push(doc.ref.update({
workers: admin.firestore.FieldValue.arrayRemove(workerId)
})); });
return Promise.all(promises);
arrayRemove is a method from the firebase documentation to remove all the occurences of an element on a following array field.
So I browsed all properties, added all promises and executed them!
worked perfectly, if anyone got questions don't hesitate.

Need to write to collection in a collection in Firebase

I need to change my web app (JavaScript) I use to load products to Firebase Firestore to create a collection ('blue_bottle') in a collection ('promotions'). It use to write straight into a collection ('blue_bottle') which was sharp for time being. What do I have to add to make it write to a collection ('promotions') first, then to collection ('blue_bottle')
I can't seem to find very much JavaScript and Firebase reference.
form.addEventListener('submit', (e) => {
e.preventDefault();
db.collection('blue_bottle').add({
Obviously this was the first thing I tried without success:
form.addEventListener('submit', (e) => {
e.preventDefault();
db.collection('promotions').db.collection('blue_bottle').add({
Now it first need to go to a collection ('promotions') please.
Thank you
The Firestore content model is that a document can only exist in a collection, and a subcollection can only exist in a document. There is no way to nest a collection directly under a collection.
To add something under a nested collection under a document, the syntax is:
db.collection('promotions').doc('the parent document').collection('blue_bottle').add({
...
})
Or shorter:
db.collection('promotions/the parent document/blue_bottle').add({
...
})

deleting specific part of field in firebase (Angular)

I am trying to remove part of an object in firebase. This is what it looks like in the database:
this is within a specific user id inside a 'users' collection.
The way I am currently trying to delete it:
removeUserLikedProperty(property_id: string) {
console.log(property_id)
return fromPromise(this.usersCollection.doc(`${this._auth.currentUserId}/test/${property_id}`).delete());
}
this is within my service. Then I have this in my ts file:
removeUserLikedProperty(property_id: string) {
this._user.removeUserLikedProperty(property_id);
console.log(property_id)
}
and then finally call this on click in my html:
<button class="button button-previous" (click)="removeUserLikedProperty(property?.property_id)">unlike</button>
From everything that I have read, this is my understanding of how to delete a member of a field. By accessing the users collection, getting user id, then going into 'test' and then removing the specific id. Anyone have any further knowledge on this? May syntax may be completely off!
You're mixing documents and fields. Please Read the documentation about data model
Either way, from the image what I understand you're trying to achieve is to delete a field in a nested object.
You need to know two things: how to delete a field in a document and how to access a field in a nested object
The following should work:
removeUserLikedProperty(property_id: string) {
console.log(property_id);
return fromPromise(this.usersCollection.doc(`${this._auth.currentUserId}`).update({
[`test.${property_id}`]: firebase.firestore.FieldValue.delete()
})
);
}

Returning documents in Cloud Firestore

I'm absolutely new to Firestore and for some reason I can't get it right.
I'm trying to retrieve documents from it that I've just manually entered. Using node.js I make a call for a database snapshot like in the documentation:
db.collection('categories').get()
.then((docs) => {
res.json(docs)
})
But instead of an array of docs or something like this, I get this as a response:
_size is right, I have two documents in the collection - but I can't find them anywhere. What am I missing here?
Your docs variable is of type QuerySnapshot. Look at the methods available on that object. If you just want the raw documents out of it, use the docs property on it to get an array of QueryDocumentSnapshot objects. Each of those will have a method called data() on them to get the raw document data.

Categories

Resources