I'm using firestore database and I am trying to retrieve data from a collection, but the data is related to another document in another collection.
What I'm trying to do is the following:
exports.acc = functions.https.onRequest(async (req, res) => {
let docRef = admin.firestore().collection('LoggedIn').doc('CurrentLogin');
snapshot = await docRef.get();
doc = snapshot.data();
usr = doc["Email"];
// I want to get the Level from the Current Logged In user (the 'usr' below)
let docRef1 = admin.firestore().collection('Accounts').doc(usr);
snapshot1 = await docRef1.get();
doc1 = snapshot1.data();
usr1 = doc1["Level"];
return res.send(usr1);
});
I've spent the last day just trying and trying with no luck, if I do one document it works, for example when I do this:
exports.acc = functions.https.onRequest(async (req, res) => {
let docRef = admin.firestore().collection('LoggedIn').doc('CurrentLogin');
snapshot = await docRef.get();
doc = snapshot.data();
usr = doc["Email"];
return res.send(usr);
});
It really returns the email address for the current logged in user.
why is the code above not working? what am I doing wrong ?
Any help is greatly appreciated
Thank you :)
I fixed the problem, turns out it was because the 'Level' is an integer value, so I had to add toString(), like that:
usr1 = doc1["Level"].toString();
Related
Hi I am building some kind of voting system and I have like to prevent the same user from voting in the same post.
let db = firebase.firestore();
var postRef = db.collection("posts").doc(this.pid);
postRef.update({
votes: firebase.firestore.FieldValue.increment(1)
});
var userRef = db.collection("users").doc(this.userId);
userRef.update({
votes: firebase.firestore.FieldValue.arrayUnion(this.pid)
});
//run this line if pid is added
this.votes = this.votes + 1;
I have like to increase the vote only if pid is added to the votes array. I wonder if arrayUnion is able to provide some kind of feedback on this or anyway I can do that.
You can look at this post and you can see that the same person can vote multiple times on the same post.
Unfortunately, by design increment and arrayUnion don't provide any callback.
In order to implement your requirement, you need a transaction (used by both increment and arrayUnion under the hood):
const postRef = db.collection("posts").doc(this.pid);
const userRef = db.collection("users").doc(this.userId);
db.runTransaction(async (t) => {
const post = await t.get(postRef);
const user = await t.get(userRef);
if (!user.get('votes').includes(this.pid)) {
t.update(postRef, {votes: post.get('votes') + 1});
t.update(userRef, {votes: [...user.get('votes'), this.pid]});
}
});
https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
https://firebase.google.com/docs/reference/js/firebase.firestore.Transaction
https://firebase.google.com/docs/firestore/manage-data/transactions#transactions
i am new this website and to mobile programming.
My questions is:
In firebase i have a collection path with some documents.
.collection(maybe).doc(random)
Each doc has subcollection as well.
Also each doc has data such as:
roomName: randomName
roomPassword: randomPass.
So, now i would like to use the query with .where operator and .get like this:
const docRef=db.collection(‘maybe’)
docRef.where(‘roomName’ ‘==‘ ‘randomName’).get()
My question is what do i get back? As i understand i get the querySnapshot, but i do not fully get how to get the second field in data specifically i.e. how to get roomPass?
const docRef = db.collection(‘maybe’);
const futureSnapshot = docRef.where(‘roomName’,‘==‘,‘randomName’).get();
gives you a promise of snapshot.
You have to "await".
const docRef = db.collection(‘maybe’);
const snapshot = await docRef.where(‘roomName’,‘==‘,‘randomName’).get();
after that you can get your data :
const room = snapshot.data(); // undefined if your query has no results
This link could help you
Happy coding !
EDIT
If your document looks like this :
{
randomName: "a name",
randomPassword: "a password"
}
Then you get your data like that :
const room = snapshot.data(); // undefined if your query has no results
const { randomPassword } = room;
I run updateOne function inside a PUT request on the server, and apparently the function does not find the record, although it returns no error. The update does not happen.
Premises: I get an id field (not _id) inside the http request. The id is of the form <name>-stage-###. I want to change the value of the id to the same without the -stage-### part.
So I now have 2 strings: issueId which includes the 'stage' part, and bareIssue which does not.
I delete without checking the record with id = bareIssue (if it exists, it is deleted, and this part works fine).
Then I try to update the id field of the record with id=issueId, and change it to bareIssue. This does not work.
Other things that do not work:
adding or removing quotes from around the "id" or id field don't change anything
putting the $eq modifier in the query phrase doesn't change anything
Changing the id that I'm searching for to an id that does not exist doesn't change anything, in other words, if I try updateOne({id:"BLABLABLAFOOBAR"}, {$set: {id:"NiceID"}}), I still get success in the .then clause of updateOne.
adding a function to the updateOne and checking for error never gives an error.
Trying to use mongo ID instead of a string as the id doesn't work.
const dbConnection = mongoose.createConnection(DbServerLocation, options);
const db = dbConnection.useDb('issuesAndFiles');
const issuesModel = db.model(ISSUES_COLLECTION_NAME, reportSchema, ISSUES_COLLECTION_NAME); // In short - it is a model
router.put('/', (req, res, next) => {
let issueId = req.query['id'];
if (issueId) {
let bareIssue = issueId.substring(0, issueId.indexOf("-stage-"));
issuesModel.findOneAndRemove({id:bareIssue}).then(() => {
const query = {$eq: {id:issueId}};
const subst = {$set :{id:bareIssue}};
let retval = issuesModel.updateOne(query, subst)
.then(() => {
console.log("Put: success in updateOne");
res.status(200).send("Approved")
}
)
})
}
else {
res.status(404).send("Issue not specified")
}
});
I expected the document to be updated. It is not.
$eq syntax is wrong. Try { <field>: { $eq: <value> } }
Try with this -
const dbConnection = mongoose.createConnection(DbServerLocation, options);
const db = dbConnection.useDb('issuesAndFiles');
const issuesModel = db.model(ISSUES_COLLECTION_NAME, reportSchema, ISSUES_COLLECTION_NAME); // In short - it is a model
router.put('/', (req, res, next) => {
let issueId = req.query['id'];
if (issueId) {
let bareIssue = issueId.substring(0, issueId.indexOf("-stage-"));
issuesModel.findOneAndRemove({id:bareIssue}).then(() => {
/* const query = {$eq: {id:issueId}};
const subst = {$set :{id:bareIssue}}; */
const query = {id : {$eq: issueId}};
const subst = {$set :{id:bareIssue}};
let retval = issuesModel.updateOne(query, subst)
.then(() => {
console.log("Put: success in updateOne");
res.status(200).send("Approved")
}
)
})
}
else {
res.status(404).send("Issue not specified")
}
});
Thank you to all who tried to help.
My problem was this: my schema did not include the item "id", and it ran in strict mode. Apparently in Robo 3T the schema was updated by someone else, but not in the code. Stupid mistake which took me all day to figure out and fix. Don't let it happen to you:)
Note to people who look for the answer: if you have a variable for the model, such as this:
const issuesModel = db.model(ISSUES_COLLECTION_NAME, issueSchema, ISSUES_COLLECTION_NAME); make sure that the issueSchema item includes the name that you want to change.
Something that was so easy in firebase database, impossible for me to accomplish in firestore. I just need to know if a record exists in a specified document.
const user = firebase.auth().currentUser.uid;
const currentPostId = this.posts[index].id;
const ref = db.collection(`likes`).doc(`${currentPostId}`); // need to know if this doc has records
The post has a store of records with just the userids that have liked the post, and a timestamp.
So far I'm able to do this:
const ref = db.collection(`likes`).doc(`${currentPostId}`);
ref
.get()
.then(snapshot => {
console.log("Exists?" + snapshot.exists); //true
})
But for the life of me I just CANNOT find a way to go one level deeper.
const ref = db.collection(`likes`).doc(`${currentPostId}/${user}`); //invalid reference segments must be odd numbers
const ref = db.collection(`likes`).doc(currentPostId).collection(user) //undefined
I've spent tthree days trying different ways. in firebase database it was just:
var ref = firebase.database().ref("users/ada");
ref.once("value")
.then(function(snapshot) {
var a = snapshot.exists(); // true
var b = snapshot.child("name").exists(); // true
var c = snapshot.child("name/first").exists(); // true
var d = snapshot.child("name/middle").exists(); // false
});
You can read the document and check whether the document has a field with the user id.
const ref = db.collection(`likes`).doc(currentPostId);
ref
.get()
.then(doc => {
console.log("Exists?" + doc.exists); //true
if(doc.exists){
var documentData = doc.data();
// Check whether documentData contains the user id
if (documentData.hasOwnProperty(userId)) {
// do something
}
}
})
The code above is not tested but it should work.
A hint! You can and should store timestamps, which are generated on the client side with the firestore server timestamp:
admin.firestore.FieldValue.serverTimestamp();
Because, if the client have changed the local time you could get a wrong time.
I'm using Cloud functions to count how many comments there are on a post.
When i add a comment it saves it in the firebase database and then on Cloud functions there is a functions that listen to "Comments" node and should "+1" back to firebase database.
For some reason it works only when i delete the comment from firebase database.
when i delete the comment its add "+1".
Thats my code
exports.commentsCount = functions.database.ref('/comments/{commentid}/{userUID}').onWrite(event =>{
const collectionRef = event.data.ref.parent;
const model = event.data.previous.val();
const commentid = event.params.commentid;
console.log("commentID:",commentid);
const countComments = collectionRef.child('countComments');
return countComments.transaction(current => {
console.log('Before the If');
if (!event.data.exists() && event.data.previous.exists()) {
console.log('Enter to the if.');
const commentsList = admin.database().ref(`comments/${commentid}/countComments`).transaction(current => {
return (current || 0) + 1;
});
}
}).then(() => {
console.log('Comments counter updated.');
});
});
Anyone can tell me where im doing wrong?
You're using this to determine when your function gets triggered:
exports.commentsCount = functions.database.ref('/comments/{commentid}/{userUID}').onWrite(event =>{
Key here is that you use onWrite, which means that this function gets triggered for any write operation under /comments/{commentid}/{userUID}.
Since you're only adding to the count, your function should only run when a new comment is added. For that you should use onCreate instead of onWrite:
exports.commentsCount = functions.database.ref('/comments/{commentid}/{userUID}').onCreate((snapshot, context) =>{
const collectionRef = snapshot.ref.parent;
const model = snapshot.val();
const commentid = context.params.commentid;
I also updated the parameters to match with the 1.0 Firebase Functions library. See the upgrade guide for more on that.