I'm currently ripping my hair out trying to query a nested collection in my Firestore db.
my db is set up as follows:
users (collection)
- username
- displayName
- ratedItems (collection)
- itemId
- timestamp
- likedItem
I want to be able to add/update the rated item in the ratedItems collection for a specific user but I seem to be hitting 2 problems:
I assume the query is incorrect as if(querySnapshot.empty) always returns false even if there are no matching items (matching the itemId) in the ratedItems collection, so it always attempts to add a new item which results in duplicate entries in the collection.
if I force the code to bypass the conditional it throws an error when it attempts to update the existing item:
Expected type 'mc', but it was: a custom yc object
My thoughts are I am using the collectionGroup query incorrectly but I haven't found a solution for this yet. Should I even be using collectionGroup at all?? from what I've read, if I understand correctly this will query every ratedItem collection regardless of the user, which isn't what I want
const rateItem = async (itemId, liked) => {
try {
const itemRef = collection(db, 'users', currentUser.uid, 'ratedItems');
const q = query(
collectionGroup(db, 'users', currentUser.uid),
where('itemId', '==', itemId)
);
const querySnapshot = await getDocs(q);
if (querySnapshot.empty) {
await addDoc(itemRef, {
itemId: itemId,
timestamp: serverTimestamp(),
likedItem: liked,
});
} else {
await updateDoc(itemRef, {
timestamp: serverTimestamp(),
likedItem: liked,
});
}
} catch (err) {
console.log(err.message);
}
};
CodePudding user response:
I assume the query is incorrect as if(querySnapshot.empty) always returns false even if there are no matching items (matching the itemId) in the ratedItems collection, so it always attempts to add a new item which results in duplicate entries in the collection.
You used the itemRef
for both of addDoc
and updateDoc
which is not the proper way to do it. You need a correct query syntax in order to update your Firestore document.
if I force the code to bypass the conditional it throws an error when it attempts to update the existing item
You can try the code below to update your nested document:
const updateitemRef = query(
collection(db, 'users', 'user_item', 'ratedItems'),
where('itemId', '==', itemId)
);
const itemSnapshot = await getDocs(updateitemRef);
itemSnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
updateDoc(doc.ref, {
likedItem: liked,
timestamp: serverTimestamp()
});
});
For the complete code, you can try the code below:
const rateItem = async (itemId, liked) => {
try {
const q = query(
collectionGroup(db, 'users', currentUser.uid),
where('itemId', '==', itemId)
);
const querySnapshot = await getDocs(q);
const additemRef = collection(db, 'users', currentUser.uid, 'ratedItems');
const updateitemRef = query(
collection(db, 'users', currentUser.uid, 'ratedItems'),
where('itemId', '==', itemId)
);
const itemSnapshot = await getDocs(updateitemRef);
if (querySnapshot.empty) {
await addDoc(additemRef, {
itemId: itemId,
likedItem: liked,
timestamp: serverTimestamp()
});
} else {
itemSnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
updateDoc(doc.ref, {
likedItem: liked,
timestamp: serverTimestamp()
});
});
}
} catch (err) {
console.log(err.message);
}
};
For more references in creating a query, you can refer to the guides below: