firebase cloud write data with a "key" paramter - javascript

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.

Related

How to eliminate extra uid from appearing in firebase push

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});

Firebase orderByKey().startAt() not working as expected. What's wrong?

I'm trying to get firebase data from a node which uid must start with a passed string.
I tried a code but I always get the same data. The database data is as following:
And I'm using the following code:
var ref = firebase.database().ref("restaurantes/history");
ref.orderByKey().startAt(userUID).once("child_added", function(snapshot) {
snapshot.forEach(child => {
if(child.key == "orders")
{
console.log(child.val());
_.each(child.val(), (value, key) => {
arrtmp.push(value)
})
}
})
If user is "FKQLlqa" I should get the history data shown in the picture. If I user is "abc" I shouldn't get any data. But I always get the data shown in the picture. Should I use another way of querying? Or I should use a key field inside orders and payments data?
Regards!
Try the following:
var ref = firebase.database().ref("restaurantes/history");
ref.child(userUID).once("value", function(snapshot) {
if (snapshot.exists()) {
console.log(snapshot.val());
}
else {
console.log("different user");
});
This will check if the snapshot that contains the userId (added as a parameter in the child() method), already exists in the database then you will be able to retrieve the data under the userId.
For reference:
https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#exists
Peter's answer is the correct solution. I'm merely adding this for completeness.
When you call orderBy... on a Firebase reference, the database orders all child nodes on the key/value/child that you specify.
If you then subsequently call startAt(...) on the query, it finds the (first) node that starts with that value and starts returning all results from there. So if you start at FKQLlqa, it will start returning keys at FKQLlqa and then return all keys after it.
If you want to return the child node(s) with a specific key/value/child, you'd use equalTo(...). So:
ref.orderByKey().equalTo(userUID).once("child_added", function(snapshot) {
...
But as Peter said already, this is just a more expensive way to look up a child with a known key. I highly recommend using his better approach: ref.child(userUID).once("value".

Firebase getting the reference

The full path for my reference looks like this
data/-KdWI6HAF0_wh9-NTEpe/films/thelobster/rating
and I can set it with
firebase.database().ref('data/-KdWI6HAF0_wh9-NTEpe/films/thelobster/rating')
.set(5);
The problem is that both the keys -KdWI6HAF0_wh9-NTEpe and thelobster are dynamic.
It makes it more difficult than it should be, is there any way to build this with just the -KdWI6HAF0_wh9-NTEpe key and make the film name a wildcard? Oris there a better way I am missing?
You can use Firebase's child() method:
firebase.database().ref('data').child(key).child('films').child(filmKey).child('rating').set(5);
Alternatively you can use ES6 string interpolation:
firebase.database().ref(`data/${key}/films/${filmKey}/rating`).set(5);
Firebase returns 'key' which is the id used to reference your object. Something like this.
var ref = firebase.database().ref("users/ada");
ref.once("value")
.then(function(snapshot) {
var key = snapshot.key; // "ada"
var childKey = snapshot.child("name/last").key; // "last"
});
You can read more about it here.
For 'thelobster', you can console.log() the data that comes from firebase, check the location of the dynamically changing 'thelobster', set it to a variable, and use the variable in your url.
Because I don't know how your incoming data looks like, I can't provide you with that code.

Match value of array from database object in Firebase Cloud Functions

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.

Cloud Functions for Firebase to index Firebase Database Objects in Algolia

I went through docs, github repositories but nothing worked for me yet.
My datastructure:
App {
posts : {
<post_keys> : {
auth_name : "name",
text : "some text" //and many other fields
}
}
}
1) Github repository : If I use this, I only get one field from one function, if I need all the fields, I would need to write separate functions for each, which is a bad approach.
2) Algolia Official Docs for Node.js : This cannot be deployed as a cloud function, but it does what I intend to do.
How can I write a function that can be deployed on Firebase and gets the whole object indexed with its key in Algolia?
Okay so I went ahead to create a Firebase Cloud function in order to index all objects in the Algolia index. This is the solution:
What you were doing is something like this:
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(event => {
What you should do is the following:
exports.indexentry = functions.database.ref('/blog-posts/{blogid}').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
var firebaseObject = event.data.val();
firebaseObject.objectID = event.params.blogid;
return index.saveObject(firebaseObject).then(
() => event.data.adminRef.parent.child('last_index_timestamp').set(
Date.parse(event.timestamp)));
});
The difference is in the first line: In the first case, you only listen to text changes, hence you only get the data containing the text change.
In the second case, you get the whole object since you listen to changes in all of the blog object (notice how /text was removed).
I tested it and it works for me: whole object including author was indexed in Algolia.

Categories