Firebase Collection Group Query in VueJS - javascript

created() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.userID = user.uid;
console.log(this.userID);
} else {
console.log('User is not logged in.');
this.$router.push('/login');
}
});
},
data() {
return {
pantry: [],
userID: '',
};
},
methods: {
getCategoryDataFromFirebase() {
const db = firebase.firestore();
db.collectionGroup("pantry")
.where("UserID", "==", this.userID)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.pantry.push(doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
},
},
};
I am attempting to do a Collection Group Query where I grab all of the listings in my firestore database that are associated with the user ID that created them. I am able to get the user ID on the created hook and store it in my this.userID. I want to then use that ID on my getCategoryDataFromFirebase function to do the collection group query.
It's recommended to create the collection group query and get the SDK error back from firebase in the console, then use the attached link in the console to create the appropriate rules automatically instead of manually which I did. Now I am thinking that I must not be referencing the group correctly because I am unable to get any data back from my firestore. I have tried to create the group by the main "pantry" but I am thinking that I would possible need to drill down further into the database or to set up the query another way. I would appreciate any guidance that could be given. I have attached the view of my firestore as well for reference. I am attempting to get all of the userIDs in each category i.e. fruits, vegetables, etc.

When you use db.collectionGroup("pantry") you are reading from all collections named pantry. In your code that is only a single top-level collections.
If you want to read from all Vegetables collections, you need to query db.collectionGroup("Vegetables").

Related

Why can't I get the sub-collection items in firebase in react in 2022

So i've been researching about how do i get the subcollection of firebase documents. Basically its .get() but its not working now in 2022 I THINK. I have the code in below...
Let say this one I will create a subcollection path with the collections.
await setDoc(doc(db,list2[i],`${currentUser?.email}-${uid}`,`single_item`,`image`),{
creator:username,name:name,img:downloadURL,email:currentUser?.email
})
await setDoc(doc(db,list2[i],`${currentUser?.email}-${uid}`,`group_item`,`images`),{
creator:username,name:name,img:downloadURL,email:currentUser?.email
})
Now i'm getting all the items of firebase documents with these...
export const owneritemsRef = collection(db,'owner_items')
export const singleItemsRef = collection(db,'owner_items/single_item/image')
export const groupItemsRef = collection(db,'owner_items','group_item',`images`)
Now when I tried to read it in my react file...
useEffect(() => {
console.log(singleItemsRef)
const unsubscribe = onSnapshot(singleItemsRef,snapshot => {
console.log(snapshot)
setSearchFilter(snapshot.docs.map((doc,idx) => {
console.log(doc.data())
return {
...doc.data(),
name:doc.data().name
}
}))
setSearchList(snapshot.docs.map((doc,idx) => {
console.log(doc)
return {
...doc.data(),
name:doc.data().name
}
}))
})
return () => {
unsubscribe()
}
},[])
It doesn't show anything...like it is completely null.. but I can see the pathsegments of singleRef... How do I get those documents please? The diagram is like this
owner-items -> (single/group) -> image/s -> { document items }
A collection group consists of all collections with the same ID and the subcollections live under a specific document. To access the subcollection you'll need to specify that particular ID in the path reference.
Using Collection Group Queries might be the easiest way to fetch all documents from collections with the same name which are passed in the collectionGroup() method.
You need to use collection() to get a CollectionReference instead of doc() which returns a DocumentReference.
Also check these similar examples for Get Subcollection and fetching subcollection documents.
UPDATE
If you need to get that specific nested subcollection you could try something similar to below
db.collectionGroup("orders").get().then((querySnapshot) => {
console.log(querySnapshot.docs.map(d => ({id: d.id, ...d.data()})))
})

Firestore web multiple posts under same uid

Firestore referenceI fixed most of my other issues but what I've been stuck on for today is figuring how to get a user to have multiple posts under the same uid.
Each post is under the, Post:"", field and everything I tried didn't work. Any tips or solutions?
const textToSave = inputTextField.value;
docRef.collection("ask").doc(user.uid).add({
Post: textToSave
}).then(function () {
console.log('saved')
}).catch(function (error) {
console.log('error');
})
You are trying to add() a document to a document, which is not valid. Documents can only be added to collections. You could do something like:
docRef.collection("ask")
.doc(user.uid)
.collection("posts")
.add({Post: textToSave})
or you could store multiple posts in an array inside the same doc, something like:
docRef.collection("ask")
.doc(user.uid)
.update({
posts: firebase.firestore.FieldValue.arrayUnion({Post: textToSave})
})

Get fields from nested DocumentReference item in Firestore

I'm in the process of writing an API using firebase functions: api is written in javascript.
In my firestore db, I have a user document that contains some nested fields. For example, my user doc has a field that looks roughly like this:
profile
education
education1 --> degree: doc ref, date: timestamp, school: doc ref
education2 --> degree: doc ref, date: timestamp, school: doc ref
I cannot for the life of me access the degree object and get the properties out of it. Each user could have multiple education entries (for example, people who hold multiple degrees). I can't step into those education# maps and access the fields inside the document they are referring to.
You didn't give a lot of details on your exact data model: which collection, which document, etc...
However, since in your comment above you say that "profile is a map, education is a map that lives inside of profile, and education items are also maps that live inside of education" the following should do the trick
var docRef = firestore.collection('collectionId').doc('docID');
docRef
.get()
.then(doc => {
if (doc.exists) {
const educationObj = doc.data().profile.education;
const promises = [];
Object.keys(educationObj).forEach(key => {
promises.push(firestore.doc(educationObj[key].degree.path).get());
});
return Promise.all(promises);
} else {
// doc.data() will be undefined in this case
console.log('No such document!');
throw new Error('no doc');
}
})
.then(results => {
results.forEach(r => {
console.log(r.data());
});
})
.catch(error => {
console.log('Error getting document:', error);
});
The degree property contains a DocumentReference, therefore you need use the path property in order to get the corresponding document.

Get Cloud Firestore database collection

I'm trying to get data from my database hierarchy db.collection/doc/collection/
I need to get the data from the collection "product"
I can already filter out the right document, by using this snippet.
Still, didn't manage to get any data from the next collection.
db.collection('deliveryservice').where('owner_id', '==', user.uid).collection('product').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
Please try the following way to retrieve data from your product collection.
var docRef = db.collection("deliveryservice").doc(user.uid).collection('product');
docRef.get().then((snapshot) => {
snapshot.docs.forEach(doc => {
}
}).catch(function(error) {
console.log("Error getting document:", error);
})

Better way of filtering data with Cloud Firestore

I'm trying to build a web chat application. I'm utilizing Firebase as a backend and Vuex. I have a logged in user, conversations, messages and users. The conversation document - in Firebase's Cloud Firestore - has an array of the messages belonging to that conversation and another of the list of users who belong to that conversation.
When my conversation container component is opened, I retrieve the conversations through an action and commit the changes:
Action:
async get({commit, rootState}) {
let convoRef = rootState.db.collection('conversations');
let conversations = await convoRef.get();
conversations.forEach(conversation => commit('SET_CONVERSATION', {conversation}))
}
Mutation:
SET_CONVERSATION(state, {conversation}) {
let user = firebase.auth().currentUser;
const data = conversation.data();
let users = data.users;
_.forEach(users, function (value, key) {
if (value.id === user.uid) {
state.all = {
...state.all,
[conversation.id]: {
id: conversation.id,
users: data.users,
name: data.name,
created: data.created,
messages: []
}
};
state.allIds.push(conversation.id);
}
});
}
I filter out the appropriate conversations with
if (value.id === user.uid)
Where user.uid is the id of the logged in user.
Problem with this approach is that I'm getting all the conversations that do no belong to the logged in user and then filtering. Is there a way to filter out the data before issuing the mutation? I tried going through Firestore's docs but there doesn't seem to be a way to natively filter out documents based on values in nested collections in said document. Thanks.

Categories