Eliminating documents from Firebase Realtime database (Not the entire collection) - javascript

I have deployed an app with React and I am using Firebase Realtime database to store some info about attention tickets in a call center. The database will store aprox 80 tickets info per day, but this is cumulative. I want to avoid this so I will not reach the firebase storage limit.
My idea so far is to delete every day at noon the tickets from the database, so It will only store the data from the current date and eliminate it at noon.
I am using remove() function from firebase, but when I tried referencing to the collection, It was entired deleted, I just want to delete the documents but not the entire collection.
Is there a way to specify Firebase to delete docs only, maybe to delete every docs except one?
This is the bunch of code that I pretend to use for deleting (Based on JS)
function deletedata(){
const dbRef = query(ref(db,'/mycollectionpath'));
onValue(dbRef, (snapshot)=>{
snapshot.forEach(childSnapshot=>{
let keyName = childSnapshot.key;
remove(dbRef);
})
});
}
setInterval(deletedata,1000)

The Firebase Realtime Database automatically creates parent nodes when you write a value under them, and it automatically deletes parent nodes when there are no longer any values under them. There is no way to have a node without a value.
If you want to keep the node, consider writing a dummy value. For example, this would remove all child nodes from mycollectionpath and replace them with a single true value:
const dbRef = ref(db, '/mycollectionpath');
dbRef.set(true);

Related

Firebase Realtime Databse difference between data snapshots

If I have a database structure like here and I make a query as shown below.Is there a difference on the traffic used to download the snapshot from the database if I access each node with snapshot.forEach(function(childSnapshot) and if I don't access the nodes?
If there is no difference, is there a way to access only the keys in Chats without getting a snapshot data for what each key contains.I'm assuming that this way it will generate less downloaded data
var requests = db.ref("Chats");
requests.on('child_added', function(snapshot) {
var communicationId = snapshot.key;
console.log("Chat id = " + communicationId);
getMessageInfo(
communicationId,
function() {
snapshot.ref.remove();
}
);
When you call requests.on('child_added', ...), you are always going to access all of the data at the requests node. It doesn't matter what you do in the callback function. The entire node is loaded into memory, and cost of the query is paid. What you do with the snapshot in memory doesn't cost anything else.
If you don't want all of the child nodes under requests, you should find some way to filter the query for only the children you need.
As they mentioned in the documentation, either of these methods can be used:
Call a method to get the data.
Set a listener to receive data-change
events.
Traffic depends upon our usage. When your data need not get updated in realtime, you can just call a method to get the data (1) But if you want your data to be updated in realtime, then you should go for (2). When you set a listener, Firebase sends your listener an initial snapshot of the data, and then another snapshot each time the child changes.
(1) - Example
firebase.database().ref('/users/').once('value') // Single Call
(2) - Example
firebase.database().ref('/users/').on('child_added') // Every Update It is Called
And also, I think you cannot get all keys, because when you reference a child and retrieve a data, firebase itself sends it as key-value pairs (DataSnapshot).
Further Reference: https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot
https://firebase.google.com/docs/database/web/read-and-write

firebase get recently added snapshot value (only one)

How to retrieve only one recently added child value from firebase without timestamp comparision?
I want to get the same key/value (only one child, not full array of child nodes) on the client side while adding it through my firebase console.
{users:
"id-ue3": "bob",
"id-om4": "john", // <-- recently added
"id-ker": "kevin"
}
firebase.database().ref().on('child_changed', function(snapshot) {
....
console.log(last_name); // output --> "john"
});
There is no way in your JSON to know what data was most recently added. Since the Firebase Realtime Database doesn't keep any metadata about when data was added, you'll need to include the necessary information in your JSON.
Two ways to do that:
Add a timestamp property to your data. You can either use the client-side time for this, or let Firebase generate a server-side timestamp when it writes the data into the database.
Encode the necessary information in the key of the items by adding them with push(). For more on these IDs, see this blog post about push IDs.
Note that you'll likely need to listen to the child_added event. The child_changed event only fires when you update a child node, not when you add a new child node.

Retrieve count data from Firebase like MySQL

When trying to pull data from a MySQL database, I can do something like:
SELECT * FROM users ORDER BY id WHERE vehicle = car
That should get me all the users that drives a car and not show users that drives a motorcycle for instance.
Is there something like this for Firebase? I can only retrieve specific data from one user?
My firebase database is like this: user -> user info (name, age, vehicle etc..)
I want to query every user that drives a car and display them in a row. How do I do that?
I have tried the following, but I didn't succeed with what I tried to do, since after users the users id is the next child. Is there a way to query past that?
var recents = firebase.database().child('users').orderByChild('department').equalTo(department);
recents.on('child_added', function(snapshot) {
var countOfUserInDepartment = snapshot.count;
document.querySelector("#cphCount").innerHTML = countOfUserInDepartment;
});
There are no count queries (nor other aggregation queries) in the Firebase Database. Your options are:
Retrieve all data matching your query and count client-side
Keep a separate count-node that you update whenever you add/remove items.
For #2 you may find it convenient to use Cloud Functions, for which there an an example of keeping such a counter.
Also see:
Firebase count group by
Database-style Queries with Firebase
In Firebase, is there a way to get the number of children of a node without loading all the node data?
How to get size of an element/list in Firebase without get it all?

Firebase get all values of specific key

I have a users table on Firebase and each user has an email prop.
Structure looks like:
Users -> User UID (looks like n8haBbjgablobA2ranfuabu3aaaga2af) -> User Obj which includes email prop.
I'd like to get an array of all the users' emails (~1m).
How can I most efficiently do this?
Ps.:
I tried:
usersRef.startAt(0).endAt(20).once("value", function(snapshot) {
console.log('FIRST 20');
console.log(snapshot.val()); // null
});
But that fails.
Probably the most efficient approach in terms of data reads would be to denormalize your data. You could store the email addresses both in the individual user nodes and in an emailAddresses node. Then you could just query the emailAddresses node directly for your list of emails.
Still ~1m email address nodes would probably be too much all at once. I'd probably grab it in chunks... I'm guessing.
Update
"Grabbing in chunks" is essentially pagination. I would try to use something off the shelf before trying to roll my own pagination solution.
Pagination libraries to check out:
Firebase Utils Pagination: This is developed by Firebase, but they say it is experimental and not ready for production use. But, it's probably still worth messing around with.
firebase-paginator: this is developed by a community member and it seems pretty solid.
If you want to roll your own pagination, check out:
#kato's response in this StackOverflow answer He makes an interesting point about the potential problem with paginating a real time data set, but then provides some good starter code
Here's a good blog entry that talks about the code that I think is a part of the firebase-paginator library I linked to above
Everybody in their answers said that it was an easy thing, yet had no working solutions. Here's what I came up with:
usersRef.orderByChild('uid').limitToFirst(100).once('value', function (snapshot) {
var users = snapshot.val()
var uids = Object.keys(users);
var lastUid = uids[uids.length - 1];
// could be another property than uid, for example email, or username. Ps.: Consider that the last ID from the previous chunk will be duplicated.
usersRef.orderByChild('uid').startAt(lastUid).limitToFirst(100).once('value', function (snapshot) {
var users = snapshot.val()
var uids = Object.keys(users);
console.log(uids);
var lastUid = uids[uids.length - 1];
// re-run function until done
})
})
Since this is a one-time deal, an option is to simply iterate over each node in the parent 'data' node capturing the child data, stripping out the email address and dumping that to a file.
the event you want is
child_added: retrieve lists of items or listen for additions to a list
of items. This event is triggered once for each existing child and
then again every time a new child is added to the specified path. The
listener is passed a snapshot containing the new child's data.
and the code to iterate all of the child nodes in the data node is
var dataRef = firebase.database().ref('myRootRef/data');
datRef.on('child_added', function(data) {
//data.val() will contain the child data, such as the email address
//append it to a text file here (for example), save to disk etc.
});
The key here is that this event is triggered once for each child, similar to iterating over all of the indexes in an array.
This will retrieve each child and present it to your app, one child at a time, iterating over all the children within the node.
It's going to take a while with that many nodes to chew through.

Create a dynamic array on a node server from the firebase database that updates with child_removed

My goal is is to create an array on a nodeJS server that is constantly updating based on data that is changing in the backend on the firebase realtime database.
Once the data is in an array, I need to perform a calculation with MathJS, then push this new value into a separate location in my firebase database. I am able to store everything on my node server in an array initially with child_added, perform my calculation, and push it to firebase. I am also able to update my calculation when new submissions are being added from the client into the database.
var db = firebase.database();
// Event Reference
var specificEvent = db.ref('/posts/area/eventID')
var sampleArray = [];
specificEvent.on("child_added", function(snapshot) {
var newPost = snapshot.val();
//push data to array
sampleArray.push(newPost.userSubmittedNumbers);
//calculation
console.log(math.mean(sampleArray));
My problem is that I have no way of tracking which specific item I want removed from the array when child_removed is called. I thought about using the firebase generated key with each post as a key/value pair, but I believe with MathJS, everything needs to be in just an array. Would dropping MathJS and using an alternative, or simply using just code be the only solution?
Any thoughts or suggestions would be greatly appreciated. Thanks!
How about storing the key/value pairs as you already considered, then – assuming you don't mind another library – using Underscore's pluck() to get the values into an array that you can do the maths on?

Categories

Resources