My database looks like this:
I am trying to get the first child of unassignedBeaconIDs, read the data beaconID, major, minor and delete it from unassignedBeaconIDs.
Here is my code:
var refBeaconID = firebase.database().ref(pathToBeaconIDs).limitToFirst(1);
refBeaconID.once('value', function(snap)
{
var firstItem = snap.val(); // first item, in format {"<KEY>": "<VALUE>"}
console.log("The first item");
console.log(firstItem.beaconID);
refBeaconID.child(firstItem.key).removeValue;
});
The problem is the childAutoID Value. I always get undefined as a result.
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So you'll need to loop over the children of the snapshot in your callback:
var refBeaconID = firebase.database().ref(pathToBeaconIDs).limitToFirst(1);
refBeaconID.once('value', function(snap)
{
snap.forEach(function(child) {
var firstItem = child.val();
console.log("The first item");
console.log(firstItem.beaconID);
});
});
I'm not completely certain what refBeaconID.child(firstItem.key).removeValue; translated to, but if you want to delete the child after logging it: child.ref.remove();.
Related
I am retrieving data from firebase and storing it into list items. But I want to reverse the order, which will bring new posts at the top. What should I add to make it work that way?
JsFiddle of my code
This is my function for retrieving the data
const dbRef = firebase.database().ref();
const usersRef = dbRef.child('users');
readUserData();
// READ
function readUserData() {
const userListUI = document.getElementById("user-list");
usersRef.on("value", snap => {
userListUI.innerHTML = ""
snap.forEach(childSnap => {
let key = childSnap.key,
value = childSnap.val()
let $li = document.createElement("li");
// edit icon
let editIconUI = document.createElement("span");
editIconUI.class = "edit-user";
editIconUI.innerHTML = " ✎";
editIconUI.setAttribute("userid", key);
editIconUI.addEventListener("click", editButtonClicked)
// delete icon
let deleteIconUI = document.createElement("span");
deleteIconUI.class = "delete-user";
deleteIconUI.innerHTML = " ☓";
deleteIconUI.setAttribute("userid", key);
deleteIconUI.addEventListener("click", deleteButtonClicked)
$li.innerHTML = value.name;
$li.append(editIconUI);
$li.append(deleteIconUI);
$li.setAttribute("user-key", key);
$li.addEventListener("click", userClicked)
userListUI.append($li);
});
})
}
While Firebase offers operations to determine the order in which nodes are returned, there is no operation to return them in descending order.
There are two common workarounds for this:
Include an inverted timestamp in the data, and order on that.
Reverse the results client-side.
In your case, it is simplest to do the latter: as you can just prepend each message to the list instead of appending it:
userListUI.prepend($li);
There are three methods to sort data with the Realtime database.
orderByChild() will order results by the value of a specified child key or nested child path.
orderByKey() will order results by child keys.
orderByValue() will order results by child values.
Find out more here
I am not able to get the email list data from firebase. All it shows is "null".
Although the variable agent0 shows the correct selected data from the array, I can't seem to use it with the firebase reference.
How can I use one of the array values to get data from firebase?
var agent0 = agents[0];
window.alert(agent0);
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins").child(agent0);
refPullEmail.once("value")
.then(function(snapshot) {
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
Database :
To retrieve the EmailList try the following:
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins").child("ALLIANCE");
refPullEmail.once("value")
.then(function(snapshot) {
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
The above will retrieve the EmailList under node ALLIANCE.
If you want to retrieve all the EmailList under node All Origins, then try the following:
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins");
refPullEmail.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot){
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
});
Here, you iterate inside the direct children of All Origins and retrieve the EmailList.
I'm retrieving an OSM Json from an overpass call, to obtain a list of features that I have to save on a database. Since the data are very different from one another (for example, some of them do have a a tag called "addr:city", and some of them not), I would like to check if a key exists, and only in that case save the corresponding value. I've found only this question but it's not my case, since I do not know a priori which keys one element will have and which not, and since I'm working with a great load of data, I really can't check the elements one by one and of course I can't write an IF for each case.
Is there a way to solve this? I was thinking something about "if key has null value, ignore it", while looping over the elements, but I don't know if something like that exists
EDIT:
This is my query:
https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(node[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696);way[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696););out%20center;
and this is the code I'm using to save the data on firebase:
results.elements.forEach(e=>{
var ref = firebase.database().ref('/point_of_interest/');
var key = firebase.database().ref().child('point_of_interest').push().key;
var updates = {};
var data = {
città: e.tags["addr:city"],
tipologia: e.tags["amenity"],
indirizzo: e.tags["addr:street"],
nome: e.tags["name"],
lat: e.lat,
lon: e.lon
}
updates['/point_of_interest/'+key] = data;
firebase.database().ref().update(updates);
})
"results" is the response in json format
You could use something like that:
var attrs = ["addr:city", "amenity", "addr:street", "name"];
var labels = ["città", "tipologia", "indirizzo", "nome"]
var data = { };
attrs.forEach((a, i) => {
if (e.tags[a]) { data[labels[i]] = e.tags[a]; }
});
You could even make this more dynamic, if you can query the attribute names and labels from somewhere.
Context
In a Firebase DB I'm storing "events" and "users". Users can have favorite events, to manage them I only store the event's id in the favorite user's DB location. So to grab favorite events informations, I need to firstable grab the event id and then go to the DB events location, to collect all the datas I need.
Problem
I would like to store in an Array all the favorite events informations (each event would be an Object with inside it : "key" : "value"), to use that Array in my HTML view and print the informations. But it doesn't work the way I coded it... :(
// This ref is too grab favorite event id (in my case only 2) in the user DB location
var refUserFavoris = firebase.database().ref().child("users/"+user.uid+"/events/favoris");
$scope.favorisTmp = $firebaseArray(refUserFavoris);
// This shows one array, with two objects (wich are my two user's favorite events) wich include ids
console.log($scope.favorisTmp);
// This is to load the objects and with the foreEach, grab there ids to use them in the next ref call
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
// This shows two lines : the id of each object
console.log(favoris.$id);
// Call a new ref to reach the event informations (in a different location of the DB) using the previous id
firebase.database().ref("events/"+favoris.$id).once('value').then(function(snapshot)
{
// Attempt to store events datas for each id I have (in my case, only two)
snapshot.forEach(function(favorisSnap)
{
var favSnap = favorisSnap.val();
// This shows a lot of "undefined" lines, wich I don't want. I would like two objects, with all informations inside
console.log(favSnap.nbPersonne);
// $scope.favorisF is an Array that I would like to use in a ng-repeat to print all datas for each event
// For now this doesn't show anything
$scope.favorisF = favSnap;
});
// If using favSnap out of the previous function, I got a "favSnap" is undifined error
console.log(favSnap);
});
});
});
<ion-item ng-repeat="f in favorisF" class="item-avatar">
{{f.nbPersonne}}
</ion-item>
EDIT 1 :
I tried a new way to have my data, but a new problem came, how to fill an Array inside a loop ? I've tried "push" and "$add" methods, but no one worked. Any ideas ?
var newFav = [];
var user;
user = firebase.auth().currentUser;
var refUserFavoris = firebase.database().ref().child("users/"+user.uid+"/events/favoris");
$scope.favorisTmp = $firebaseArray(refUserFavoris);
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
console.log(favoris.$id);
var refFavoris = firebase.database().ref("events/"+favoris.$id);
refFavoris.on('value', function(snap)
{
//This is where I'm trying to fill "newFav" in each steps of the loop
newFav.push(snap.val());
console.log("Scope newFav vaut :", $scope.newFav);
});
});
});
I think you made a typo here.
var refUserFavoris = firebase.database().ref("events/favoris/"+favoris.$id).once('value')
Thanks a lot Abdel, I fixed my problem :
Here is the solution
$scope.newFav = [];
console.log($scope.newFav);
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
console.log(favoris.$id);
var refFavoris = firebase.database().ref("events/"+favoris.$id);
refFavoris.on('value', function(snap)
{
$scope.newFav.push(snap.val());
console.log("Scope newFav vaut :", $scope.newFav);
});
});
});
How do you only pull only the nodes from firebase and not the keys using javascript? In other words, I only want the values of the key-value pairs from the below firebase, which means I don't want the unique keys below but just what's underneath.
Currently, my code is..
function PullFirebase() {
new Firebase('https://myfirebase.firebaseIO.com/quakes').on('value', function (snapshot) {
var S = snapshot.val();
function printData(data) {
var f = eval(data);
console.log(data + "(" + f.length + ") = " + JSON.stringify(f).replace("[", "[\n\t").replace(/}\,/g, "},\n\t").replace("]", "\n]"));
}
printData(S);
});
}
PullFirebase();
This produces the following in the console
[object Object](undefined) = {"-JStYZoJ7PWK1gM4n1M6":{"FID":"quake.2013p618454","agency":"WEL(GNS_Primary)","depth":"24.5703","latitude":"-41.5396","longitude":"174.1242","magnitude":"1.7345","magnitudetype":"M","origin_geom":"POINT (174.12425 -41.539614)","origintime":"2013-08-17T19:52:50.074","phases":"17","publicid":"2013p618454","status":"automatic","type":"","updatetime":"2013-08-17T19:54:11.27"},
"-JStYZsd6j4Cm6GZtrrD":{"FID":"quake.2013p618440","agency":"WEL(GNS_Primary)","depth":"26.3281","latitude":"-38.8725","longitude":"175.9561","magnitude":"2.6901","magnitudetype":"M","origin_geom":"POINT (175.95611 -38.872468)","origintime":"2013-08-17T19:45:25.076","phases":"13","publicid":"2013p618440","status":"automatic","type":"","updatetime":"2013-08-17T19:48:15.374"},...
but I'd like to only have the dictionaries , such as
[{"FID":"quake.2013p618454","agency":"WEL(GNS_Primary)","depth":"24.5703","latitude":"-41.5396","longitude":"174.1242","magnitude":"1.7345","magnitudetype":"M","origin_geom":"POINT (174.12425 -41.539614)","origintime":"2013-08-17T19:52:50.074","phases":"17","publicid":"2013p618454","status":"automatic","type":"","updatetime":"2013-08-17T19:54:11.27"},{"FID":"quake.2013p597338","agency":"WEL(GNS_Primary)","depth":"5.0586","latitude":"-37.8523","longitude":"176.8801","magnitude":"2.2362","magnitudetype":"M","origin_geom":"POINT (176.88006 -37.852307)","origintime":"2013-08-10T00:21:54.989","phases":"17","publicid":"2013p597338","status":"automatic","type":"","updatetime":"2013-08-10T03:42:41.324"}...]
If I understand you correctly, you want to get all child objects under quakes.
You generally have two approach here:
Get the value of the parent node and loop over the children
Monitor as children are added/updated/removed to the parent node
Your approach matches with #1, so I'll answer that one first. I'll also give an example of approach #2, which is more efficient when your data set changes.
Iterate children of a Firebase ref
In your on('value', handler you can skip the unique IDs using forEach:
new Firebase('https://myfirebase.firebaseIO.com/quakes').on('value', function (snapshot) {
var quakes = [];
snapshot.forEach(function(childSnapshot) {
quakes.push(childSnapshot.val());
});
var filter = new crossfilter(quakes);
});
The forEach function is sychronous, so we can simply wait for the loop to finish and then create the crossfilter.
Monitor children of a Firebase ref
In that case, the best construct is:
var quakes = new Firebase('https://myfirebase.firebaseIO.com/quakes');
var quakeCount = 0;
quakes.on('child_added', function (snapshot) {
var quake = snapshot.val();
quakeCount++;
console.log("quakeCount="+quakeCount+", FID="+quake.FID);
});
quakes.on('child_removed', function (old_snapshot) {
var quake = old_snapshot.val();
quakeCount--;
console.log("quakeCount="+quakeCount+", removed FID="+quake.FID);
});
With this code construct you're actively listening for quakes that are added and removed. You'll still have to keep an array of all the quakes, which you then modify in child_added, child_changed and child_removed.
How they compare
When you first run the code, monitoring for children will result in the same data as the on('value', construct. But when children are added/removed later on('value', will receive all quakes again, while on('child_added', and on('child_removed', will only be called for the quake in question.