I have my function on my class and i have to catch my subcollection. everything works fine with my collection (my console.log is working) but when i tried to catch something on my subcollection i have this error :
TypeError: undefined is not a function (near '...(0, _firestore.default)().collection("Teams").doc(docid).collection("membersList").where("statut", "==", "Validé").then...')
also my code :
GetMembersTeam = async () => {
firestore()
.collection("Teams")
.where("tokenTeam", "==", "c2z3f4vb3bh")
.get()
.then((querySnapshot) => {
if (querySnapshot.empty) {
console.log("no documents found");
} else {
querySnapshot.forEach((doc) => {
let Teams = doc._data;
let docid = doc.id;
firestore()
.collection("Teams")
.doc(docid)
.collection("membersList")
.where("statut", "==", "Validé")
.then(async (querySnapshot) => {
if (querySnapshot.empty) {
console.log("no documents found");
} else {
querySnapshot.forEach(async (doc) => {
let Teams = doc._data;
let docid = doc.id;
console.log(docid);
});
}
});
});
}
});
};
componentDidMount() {
this.GetViewTeam();
this.GetMembersTeam();
}
Are you missing a get()?
firestore()
.collection("Teams")
.doc(docid)
.collection("membersList")
.where("statut", "==", "Validé")
.get() //<- are you missing a get?
.then(async (querySnapshot) => {
if (querySnapshot.empty) {
console.log("no documents found");
} else {
querySnapshot.forEach(async (doc) => {
let Teams = doc._data;
let docid = doc.id;
console.log(docid);
});
}
Related
I am stuck on probably a very basic thing, but I can't seem to get the data from Firestore into the return variable "profile"
What am I doing wrong when looking at the code below?
let profile;
export const getWidgets = createAsyncThunk(
"projectDashboardApp/widgets/getWidgets",
async () => {
var docRef = db().collection("companies").doc("cmpn0000001");
docRef
.get()
.then((doc) => {
if (doc.exists) {
profile = doc.data()
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch((error) => {
console.log("Error getting document:", error);
});
return profile;
}
);
I want to pass data from /api/firestore/read.js to mainServer.js.
It does have the document, it prints, but does not return the data.
mainServer.js
app.get("/api/profile", async (req, res) => {
const uid = req.user.uid;
const userReader = new usersReader(uid);
const data = await userReader.readData();
console.log("Data", data); // data is undefined
res.status(200).send(data);
});
read.js
const admin = require("../../firebase-config").admin;
class ReadFireDb {
constructor(_uid) {
this.uid = _uid;
}
async readData() {
await admin
.firestore()
.collection("users")
.doc(this.uid)
.get()
.then((snapShot) => {
if (snapShot.exists) {
console.log(snapShot.data()); // here i print data correctly
return snapShot.data(); // here is the problem
} else {
return null;
}
})
.catch((err) => console.log(err));
}
}
module.exports = {
ReadFireDb,
};
how is the correct way to return this data?
This is the answer:`
Just make some changes to read.js
const admin = require("../../firebase-config").admin;
class ReadFireDb {
data;
constructor(_uid) {
this.uid = _uid;
}
async readData() {
await admin
.firestore()
.collection("users")
.doc(this.uid)
.get()
.then((snapShot) => {
if (snapShot.exists) this.data = snapShot.data();
})
.catch((err) => console.log(err));
return this.data;
}
}
module.exports = {
ReadFireDb,
};
this is my code:
exports.updateUserName = functions.firestore
.document("users/{userId}")
.onUpdate((change, context) => {
const newValue = change.after.data().name;
const previousValue = change.before.data().name;
const userID = context.params.userId;
var batch = admin.firestore().batch();
if (newValue != previousValue) {
//Update author in sets/{set_id}/author
admin
.firestore()
.collection("sets")
.where("authorId", "==", userID)
.get()
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref,{ "author": newValue });
});
}
}),
//Update author in courses/{course_id}/author
admin
.firestore()
.collection("courses")
.where("authorId", "==", userID)
.get()
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref,{ "author": newValue });
});
}
})
}
return batch.commit().then(() => {
console.log("commited")
});
});
So I want to update two different documents. I think I have to do this with batch().
But I get the Error:
Error: Cannot modify a WriteBatch that has been committed.
at WriteBatch.verifyNotCommitted (/workspace/node_modules/#google-cloud/firestore/build/src/write-batch.js:117:19)
at WriteBatch.update (/workspace/node_modules/#google-cloud/firestore/build/src/write-batch.js:313:14)
at /workspace/index.js:84:21
at QuerySnapshot.forEach (/workspace/node_modules/#google-cloud/firestore/build/src/reference.js:748:22)
at /workspace/index.js:83:33
at processTicksAndRejections (internal/process/task_queues.js:97:5)
This is the first time Im working with batch or have to update 2 documents with one cloud function.
What am I doin wrong?
You need to wait the asynchronous queries are completed and the batch is populated before calling commit(). For that you need to chain the promises and return this chain in the Cloud Function.
So the following should do the trick (untested):
exports.updateUserName = functions.firestore
.document("users/{userId}")
.onUpdate((change, context) => {
const newValue = change.after.data().name;
const previousValue = change.before.data().name;
const userID = context.params.userId;
const db = admin.firestore();
const batch = db.batch();
if (newValue != previousValue) {
//Update author in sets/{set_id}/author
return db
.collection("sets")
.where("authorId", "==", userID)
.get()
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref, { "author": newValue });
});
}
return db
.collection("courses")
.where("authorId", "==", userID)
.get();
})
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref, { "author": newValue });
});
}
return batch.commit();
})
.then(() => {
console.log("commited")
return null;
});
} else {
return null;
}
});
Do not forget that there is a 500 docs limit for a batched write. If you know you may go over this limit, you can use Promise.all() instead, as follows:
exports.updateUserName = functions.firestore
.document("users/{userId}")
.onUpdate((change, context) => {
const newValue = change.after.data().name;
const previousValue = change.before.data().name;
const userID = context.params.userId;
const db = admin.firestore();
var promises = [];
if (newValue != previousValue) {
//Update author in sets/{set_id}/author
return db
.collection("sets")
.where("authorId", "==", userID)
.get()
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
promises.push(doc.ref.update({ "author": newValue }));
});
}
return db
.collection("courses")
.where("authorId", "==", userID)
.get();
})
.then((querySnapshot) => {
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
promises.push(doc.ref.update({ "author": newValue }));
});
}
return Promise.all(promises);
})
.then(() => {
console.log("commited")
return null;
});
} else {
return null;
}
});
Finally, note this async/await version which is much easier to read:
exports.updateUserName = functions.firestore
.document("users/{userId}")
.onUpdate(async (change, context) => {
const newValue = change.after.data().name;
const previousValue = change.before.data().name;
const userID = context.params.userId;
const db = admin.firestore();
const batch = db.batch();
if (newValue != previousValue) {
let querySnapshot = await db
.collection("sets")
.where("authorId", "==", userID)
.get();
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref, { "author": newValue });
});
}
querySnapshot = await db
.collection("courses")
.where("authorId", "==", userID)
if (!querySnapshot.empty) {
querySnapshot.forEach((doc) => {
batch.update(doc.ref, { "author": newValue });
});
}
await batch.commit();
console.log("commited")
return null;
} else {
return null;
}
});
I am using Nuxt and it is recommended that we use async data for SSR.
I have this piece of code below:
async asyncData({ params }) {
console.log("params ...");
console.log(params.id);
let asyncDataDescription = "";
await firebase
.firestore()
.collection("posts")
.where("ytid", "==", params.id)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
asyncDataDescription = doc.data().ytDescription;
});
console.log("description ...");
console.log(asyncDataDescription);
return { aSyncDescription: asyncDataDescription };
});
},
In the console log, I can see the data correctly returned from firestore but somehow when I try to display the data:
<div>{{ aSyncDescription }}</div>
It is not showing. Do I miss anything here? The page that talks about async data is here https://nuxtjs.org/api
Do you see this .then(querySnapshot => { ?
You are returning your result to an callback function. Rewrite it like this
async asyncData({ params }) {
console.log("params ...");
console.log(params.id);
let asyncDataDescription = "";
let querySnapshot = await firebase
.firestore()
.collection("posts")
.where("ytid", "==", params.id)
.get()
querySnapshot.forEach(doc => {
asyncDataDescription = doc.data().ytDescription;
});
console.log("description fdkjfdk");
console.log(asyncDataDescription);
return { aSyncDescription: asyncDataDescription };
},
What I want to achieve is to check if a document exist based on a field like liker_id and if it exist then return and if not then create a new document with the liker_id.
I've tried both snapshot.exists and doc.exists but they seem to give weird behaviors where the console.log doesn't get triggered or collection still adds document even though it already exists.
const liker = db
.collection("post")
.doc('ubxL0nDCLHgrtEyQ5TEV')
.collection("votes")
.where("liker_id", "==", "user-TVe8mMRU47cnfO4xbl9yQEEE4XB3")
.get()
.then(snapshot => {
snapshot.forEach(doc => {
if (doc.exists) {
console.log("exist");
} else {
console.log("not exist");
}
});
})
.catch(error => {
console.log(error);
});
Would you try the code like this?
const liker = db
.collection("post")
.doc('ubxL0nDCLHgrtEyQ5TEV')
.collection("votes")
.where("liker_id", "==", "user-TVe8mMRU47cnfO4xbl9yQEEE4XB3")
.get()
.then(snapshot => {
const data = snapshot.val();
data.forEach(doc => {
if (doc.exists) {
console.log("exist");
} else {
console.log("not exist");
}
});
})
.catch(error => {
console.log(error);
});