Firebase get child_added in loop - firebase

I'm using Ionic 2.
This is my Firebase structure
I want to get the child of java and math in this firebase photo their child are 0,1 to each one.
I did something like that
public getCourse(departmentId:any):any{
var semesterRef = firebase.database().ref('Courses/'+departmentId+'/SemA')
semesterRef.on('child_added', function(courseSnapshot) {
console.log(courseSnapshot.key);
});
but it gives me just the Java and math names and not their child. How can I run in loop and get it and also return as array.
that's my code

You can use the snapshot's forEach method to iterate the key's children:
public getCourse(departmentId:any):any{
var semesterRef = firebase.database().ref('Courses/'+departmentId+'/SemA')
semesterRef.on('child_added', function(courseSnapshot) {
console.log(courseSnapshot.key);
courseSnapshot.forEach(function(childSnapshot):boolean{
console.log(childSnapshot.key);
// ... etc.
return false; // to appease TypeScript
});
});
}
The Firebase API will not return arrays, as it converts arrays to objects with keys derived from the array indices, but you can enumerate the children and re-build an array if that's what you require.

Related

How to Remove Arrays of Element in Firebase Cloud Firestore using Ionic 4

In My Cloud Firestore database structure looks like this. Now, I'd like to delete index positions based on Index 0, Index 1 like this.
const arrayLikedImagesRef = {imageurl: image, isliked: true};
const db = firebase.firestore();
const deleteRef = db.collection('userdata').doc(`${phno}`);
deleteRef.update({
likedimages: firebase.firestore.FieldValue.arrayRemove(arrayLikedImagesRef)
});
});
As explained here, “bad things can happen when trying to update or delete array elements at specific indexes”. This is why the Firestore official documentation indicates that the arrayRemove() function will take elements (strings) as arguments, but not indexes.
As suggested in this answer, if you prefer using indexes then you should get the entire document, get the array, modify it and add it back to the database.
You can't use FieldValue to remove array items by index. Instead, you could use a transaction to remove the array items. Using a transaction ensures you are actually writing back the exact array you expect, and can deal with other writers.
For example (the reference I use here is arbitrary, of course, you would need to provide the correct reference):
db.runTransaction(t => {
const ref = db.collection('arrayremove').doc('targetdoc');
return t.get(ref).then(doc => {
const arraydata = doc.data().likedimages;
// It is at this point that you need to decide which index
// to remove -- to ensure you get the right item.
const removeThisIndex = 2;
arraydata.splice(removeThisIndex, 1);
t.update(ref, {likedimages: arraydata});
});
});
Of course, as noted in the above code, you can only be sure you are about to delete the correct index when you are actually inside the transaction itself -- otherwise the array you fetch might not line up with the array data that you originally selected the index at. So be careful!
That said, you might be asking what to do given that FieldValue.arrayRemove doesn't support nested arrays (so you can't pass it multiple maps to remove). In that case, you just want a variant of the above that actually checks values (this example only works with a single value and a fixed object type, but you could easily modify it to be more generic):
const db = firebase.firestore();
const imageToRemove = {isliked: true, imageurl: "url1"};
db.runTransaction(t => {
const ref = db.collection('arrayremove').doc('byvaluedoc');
return t.get(ref).then(doc => {
const arraydata = doc.data().likedimages;
const outputArray = []
arraydata.forEach(item => {
if (!(item.isliked == imageToRemove.isliked &&
item.imageurl == imageToRemove.imageurl)) {
outputArray.push(item);
}
});
t.update(ref, {likedimages: outputArray});
});
});
(I do note that in your code you are using a raw boolean, but the database has the isliked items as strings. I tested the above code and it appears to work despite that, but it'd be better to be consistent in your use of types).

Firebase query with Vue js

i am new in Vue JS and in Firebase. My target is get all 'eventos' that has same category. I mean, let's i have two eventos, an eventos category "SMIX" and another has "DAM". Now i want to get the eventos has category 'SMIX'
My data structure is here :
created() {
var datos = []
firebase.database().ref('usuarios').on("value", data => {
data.forEach(function(user){
user.child("eventos").orderByChild("categoria").equalTo("SMIX")
.forEach(function(evento){
datos.push(evento.val())
});
});
this.eventos = datos;
});
}[My data Structure][1]
There are several errors and points to be noted in your code:
Firstly, if you receive the error user.child(...).orderByChild is not a function
it is because with data.forEach(function(user) {...}), user is a DataSnapshot (see the forEach() doc), and by calling the child() method on this DataSnapshot you get another DataSnapshot... which does not have a orderByChild() method.
The orderByChild() method is a method of a Reference, so you need to do
user.child(...).ref.orderByChild()
using the ref property of the DataSnapshot
Secondly, you cannot do
user.ref.child("eventos").orderByChild("categoria").equalTo("SMIX")
.forEach()
because you need to use the once() or on() methods to get the data at a database location represented by a Reference.
Thirdly, Since you are going to execute several queries within a loop, you need to use the once() method instead of the on() method. The on() method set a listener that continuously "listens for data changes at a particular location."
Finally, note that you need to use Promise.all() to manage the parallel asynchronous queries to the database.
So, having noted all the points above, the following code will do the trick (to put in created()):
var datos = []
firebase.database().ref('usuarios').once('value')
.then(dataSnapshot => {
var promises = [];
dataSnapshot.forEach(user => {
promises.push(user.ref.child("eventos").orderByChild("categoria").equalTo("SMIX").once('value'));
});
return Promise.all(promises);
})
.then(results => {
//console.log(results);
results.forEach(dataSnapshot => {
dataSnapshot.forEach(evento => {
datos.push(evento.val());
});
});
this.eventos = datos;
});

Cannot encode type ([object Object]) to a Firestore Value error while attempting pagination

So here I have my code
notifull.get('/getNote', (request, response) => {
// START Get variables
var requestData = {
// location properties
subject: request.query.subject,
category: request.query.category,
subcategory: request.query.subcategory,
// easy way to get full reference string
referenceString: function() {
return `${this.subject}/${this.category}/${this.subcategory}`;
},
// pagination properties
pagePosition: Number(request.query.pagePosition),
// easy way to get limit number
paginationNumber: function() {
return (this.pagePosition - 1) * 2;
}
};
// DEBUG_PURPOSES response.send(requestData.referenceString());
// END Get variables
// START Construct index
var first = admin.firestore().collection(requestData.referenceString())
.orderBy("upvotes")
.limit(requestData.paginationNumber());
// DEBUG_PURPOSES response.send(first)
// END Construct index
// START Paginate
return first.get().then(function (documentSnapshots) {
// Get the last visible document
var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
console.log("last", lastVisible);
// Construct a new query starting at this document,
// get the next 25 cities.
var next = admin.firestore().collection(requestData.referenceString())
.orderBy("upvotes")
.startAfter(lastVisible)
.limit(2);
response.send(next)
});
});
As you can see, I am attempting to Paginate using Cloud Firestore. If you'll notice, I've divided the code into sections, and the previous testing shows me the Construct Index and Get variables sections work. However, when I pulled the Paginate example from Firebase's own docs, adapted it to my code, and then tried to run, I was met with this error.
Cannot encode type ([object Object]) to a Firestore Value
UPDATE: After more testing, it seems that if I remove the startAfter line, it works fine.
According to firebase documentation, Objects of custom classes are not supported so in some languages like PHP, C++, Python and Node.js.
PLEASE HERE AS A REFERENCE.
https://firebase.google.com/docs/firestore/manage-data/add-data#custom_objects
So, I can advise to encode your objects to json and be decoding them to your custom classes when you download them from firebases.

Getting the reference from $firebaseArray to make a new reference object

Related to this question, I need to be able to get an element from a collection as a Firebase reference, ie given a $firebaseArray I need a $firebaseObject pointing to one of its elements. Unlike that example, I can't just hard-code a path the array and take a child from there because the location of the array will vary. And I can't use $firebaseArray.$getRecord() or the object provided by my ng-repeat followed by array.$save() because I may need to do a push() on this element.
So I settled on this reusable approach:
In a service:
function selectElement(array, element) {
var obj = $firebaseObject(array.$ref().child(element.$id));
return obj;
}
In the controller:
function onItemClicked(e) {
vm.selected = dataservice.selectElement(vm.observations, e);
}
In the template:
<div class="list-item" ng-repeat="o in vm.observations" ng-click="vm.onItemClicked(o)">
The first line of selectElement produces an error: array.$ref(...).child is not a function at Object.selectElement
Here array has all the properties you'd expect, but logging array.$ref() shows this obfuscated object:
Y {k: Ji, path: P, n: Ce, pc: true}
That is what it looks like from the time the array is created. What's going on here and how do I use this reference? Is there another way to get a working Firebase object out of an array?

Iterating over $firebaseArray and $firebaseObject

I am trying to iterate over firebaseObject and firebaseArray fetched from my Firebase but they don't seem like normal javascript objects and arrays.
My data is stored in the following form
'mainKey': {
'key1':'value1',
'key2':'value2'
},
'mainkey2': {
'key3':'value3'
}
I've tried the following code
var firebaseRef = new Firebase("https://<my-app>.firebaseio.com/);
var fbArray = $firebaseArray(firebaseRef);
var fbObject = $firebaseObject(firebaseRef);
for(var i=0;i<fbArray.length;i++){
console.log(fbArray[i]);
}
console.log(fbObject);
console.log(fbObject.mainkey);
console.log(fbArray.length);
This gives the following output in the console
Object { $$conf={...}, $id="test", $priority=null, more...}
undefined
0
Though the object returned has mainkey property but I'm not able to access it.Why does this happen? And how should I iterate over them ?
You could try for..in loop to iterate over an object.
Below is an example:
for (var key in fbObject) {
console.log(fbObject[key]); // You could use this method with all objects in JS
}
here's the info you need to know
The $firebaseArray service takes a Firebase reference or Firebase Query and
returns a JavaScript array which contains the data at the provided Firebase
reference. Note that the data will not be available immediately since
retrieving it is an asynchronous operation.
You can use the $loaded() promise to get notified when the data has loaded.
https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray
fbArray.$loaded(function() {
//here you can iterate over your object
});

Resources