I currently have the following push query for my firebase database.
setVisitorAttendanceDate = (orgId, attendeeUid, date) => this.db.ref(`organization/${orgId}/visitor-attendance/${date}`).push({[attendeeUid]: true});
This creates the following:
- visitor-attendance
- 2020-11-30-PM
-MNSIxmbzLwlW5Dq83Ws
-MNSIxm_woAnBAkVQWRV: true
It adds the date as expected but it adds an extra UID.
Right after the date it adds this uid for the object:
-MNSIxmbzLwlW5Dq83Ws
How can I make it to be with out that UID? So this
- visitor-attendance
- 2020-11-30-PM
-MNSIxm_woAnBAkVQWRV: true
Remember, everything in the Realtime Database are key: value pairs. When a path is defined and you .push in that path, a node with a child key: value pair is created that sits 'under' that path.
If you look at the code, you're actually defining a path to the data with the final last component being date
this.db.ref(`organization/${orgId}/visitor-attendance/${date}`).push({[attendeeUid]: true});
^^^ path ^^^ key ^^^ value
with the path being
organization
orgId
visitor-attendance
date
the pushID
MNSIxm_woAnBAkVQWRV: true
From the Firebase Documentation
The push() method generates a unique key every time a new child is
added to the specified Firebase reference.
One possible fix is to use .set as shown in the Guide
For basic write operations, you can use set() to save data to a
specified reference, replacing any existing data at that path.
firebase.database().ref('users/' + userId).set({
username: name,
email: email,
profile_picture : imageUrl
});
The above comment and answer were very helpful. I ended up solving this by changing push to update.
The code now reads:
setVisitorAttendanceDate = (orgId, attendeeUid, date) => this.db.ref(`organization/${orgId}/visitor-attendance/${date}`).update({[attendeeUid]: true});
Related
Currently I have a dashboard application and when a user adds to their dashboard it does a post request to Firestore to set the data in a certain document. Here is what that code looks like:
export function createEntry(data) { // Data has a authorId key with the value of the UID
const userEntry = firestore.collection('userEntries').doc();
userEntry.set(data);
return userEntry;
}
So above, a new entry gets created with a random ID that I then use to grab the data to display later. To get this information later, I loop through all of the entries to see where the authorId matches the user that is log in to return that.
So what I am trying to do is refactor the code so that each document in 'userEntries' is the ID of the user, authorID: UID, and have it be an array where I can keep pushing items into. In return, I can just grab the user array and map over those items to display instead of looping through all my entries and checking.
What I've tried:
export function createEntry(data) {
const userEntry = firestore.collection('userEntries').doc(data.authorId);
userEntry.update({
userData: firebase.firestore.FieldValue.arrayUnion(data)
})
}
So to sum it up, I would like a way to set the document to users ID and push any future entries into their own array, in which I could easily access from the frontend to display.
Hope you can point me in the right direction, thank you!
You don't actually have to revise the original method. If you have the authorId as a field value, you can just query the data using where clause like this:
const uid = auth.currentUser.uid;
firestore.collection().where('authorId', '==', uid).get();
With this method, you are not getting the entire collection and looping through to see which one is written by the user.
Goal: get the creation time of a new Firestore document in the document creation process
First I create a new document with the corresponding data newDocumentData and a field creationTime with the creation time, as shown below:
const newDocumentRef = await collectionRef.add({
...newDocumentData,
creationTime: firebase.firestore.FieldValue.serverTimestamp()
})
Then, I need the creationTime, and I follow like this...
const document = await newDocumentRef.get()
if (document.exists) {
const documentData = document.data()
}
...to finally get my documentData.creationTime.
My question is: Is there any way to get creationTime with newDocumentRef in the first step and, therefore, avoiding the rest of the process?
Thank you!
No, it is not possible with the Client SDKs, "to get the value of creationTime in the first step". FieldValue.serverTimestamp() returns a sentinel value that tells the server to assign a server-generated timestamp in the written data.
In other words the exact value for creationTime will be calculated by the server, and if you want to get this value, you need to query the database for it.
Note that, on the other hand, with the Firestore REST API, when you create a document, you get back (i.e. through the API endpoint response) a Document object that contains, among others, a createTime field.
I'm reading documentation for Firebase and I came to this part:
function writeNewPost(uid, username, picture, title, body) {
// A post entry.
var postData = {
author: username,
uid: uid,
body: body,
title: title,
starCount: 0,
authorPic: picture
};
// Get a key for a new Post.
var newPostKey = firebase.database().ref().**child('posts')**.push().key;
How am I supposed to understand this? Currently I'm thinking this is saying "from the root of the database, create a node and store its access key in a variable". What is the use of having a child function with 'posts'? I can run similar code like the following and get the same result.
var newPostKey = firebase.database().ref().push().key;
Your second bit of code does not really give the same result, when taken in the context of the rest of the code sample from the docs (that you didn't show here).
Actually, the code you've shown does not actually create any data in the database at all, because if nothing is passed to push(), then it just returns a reference to the location (with a unique key) that you can later write to. The part of the sample that you omitted actually performs the update.
The API docs for child() says:
Gets a Reference for the location at the specified relative path.
The method is helping you build a path to a reference. Without the call to child() in your second example, the reference will be at the root of the database, rather than under "/posts". While you will get a unique key in both situations, its location in the database will be different (after you actually write data there).
This is my first app project using Google Cloud Functions & Firebase. I'm trying to find away to get a single value of the array that I'm returning and compare it to a set variable and if it matches, update another child's value in that same account.
My App users can add records to the database under their login/user_id that is stored in the database. I'm trying to get a list of the "RecordName" that is a child under that login/user_id that every user has stored in their account.
So basically every "RecordName" in the entire database. When I want to run specials for those records, I need to match the name of that record to the name of the record I have on special and if there is a match, update another child value under that user's account ("special" = true.). This way, when they load their app next time, I have it highlighting that record so they know it's on special.
When I use..
const ref = admin.database().ref(`/store`);
...with the following code...
ref.on('value', function(snapshot) {
// puts ALL items of the object into array using function ..
console.log(snapshotToArray(snapshot));
});
... and the function...
function snapshotToArray(snapshot) {
var returnArr = [];
snapshot.forEach(function(childSnapshot) {
var item = childSnapshot.val();
item.key = childSnapshot.key;
returnArr.push(item);
});
return returnArr;
};
... I get the entire array just as it is in the database:
-store
-{ones_users_id}
-recordname: value1
-special: false
-{anothers_users_id}
-recordname: value2
-special: false
ect. ect.
If my record on special is called, "Newbie Record", what would be the best way to take out every individual value for the key: "recordname" from the array, compare each one to var = "Newbie Record" and if they match, update the value of the key: "special" to be true?
I'm new to JSON and NodeJS, I've been searching on here for answers and can't find exactly what I'm looking for. Your feedback would be very helpful.
It sounds like you're looking to query your database for nodes that have "recordname": "Newbie Record" and update them.
An easy way to do this:
const ref = admin.database().ref(`/store`);
const query = ref.orderByChild("recordname").equalTo("Newbie Record");
query.once('value', function(snapshot) {
snapshot.forEach(function(child) {
child.ref.update({ special: true })
});
});
Main differences with your code:
We now use a query to read just the nodes that we want to modify.
We now use once() to read the data only once.
We loop over the children of the snapshot, since a query may result in multiple nodes.
We use the reference of each child and then update its special property.
I recommend reading a bit more about Firebase queries in the documentation.
I am learning Cloud Functions for Firebase. What I want is pass the key and value in the URL parameters, like:
https://xxx.cloudfunctions.net/addMessageSet?text=goodboy&key=testKey
And then in the Realtime Database set a testKey:goodboy.
I know use push() will generate a unique key (if i understood correctly) but I'd like use my own key each time. I am not sure if set() works.
My problem is push({originalKey:original}) doesn't work as expected. It writes:
originalKey: goodboy
Where originalKey is just key not the parameter from the URL. Is this possible or any other solutions?
The code is like below:
exports.addMessageSet = functions.https.onRequest((req, res) => {
// Grab the text parameter.
const original = req.query.text;
const originalKey = req.query.key;
admin.database().ref('/messages/').push({originalKey:original}).then(snapshot => {
console.log('goodboy', original, originalKey);
res.redirect(303, snapshot.ref);
});
});
If you want to use a key you're generating without firebase generating another you need to use set with your key in the path
admin.database().ref('/messages/' + originalKey).set(original).then(snapshot => { });
// if originalKey is not a string use String(originalKey)
You said about originalKey not beeing a url, but everything in firebase if url based, like this you're doing
myDB
|_ messages
|_ originalKey: original
and not
myDB > messages > originalKey > original
If you need another key after the messages node i recomend using a date UNIX number, momentJS is good to handle this.
Hope it helps
Using push() will indeed generate a unique key. You will need to use either set() or update().
Note that using set() will overwrite the data at the specified location including any child nodes.