Firebase orderByChild equalTo hangs when no data - javascript

see jsfiddle: http://jsfiddle.net/237ur2tf/14/
coinref.orderByChild("uuid").equalTo("xx")...
Query works fine when there is a match in the database.
When there is no match, neither the callback nor error function is called.
Am I doing something wrong?... What would be the way around this?.
Many thanks.
Pat/

That is the expected behavior. The relevant snippet from your fiddle is slightly longer:
// Get by child uuid AND uuid exists
coinsRef.orderByChild("uuid")
.equalTo("4D4B2118-0435-439C-BA7C-99B9BD0DA7F4")
.on('child_added', function(snapshot) {
This code says that "when there is an (existing or new) child added to this query, call me with its snapshot". Since there is no child, the child_added event doesn't fire.
If you want to check if there is a value, you should use a value event:
// Get by child uuid AND uuid exists
coinsRef.orderByChild("uuid")
.equalTo("4D4B2118-0435-439C-BA7C-99B9BD0DA7F4")
.on('value', function(snapshot) {
console.log("found Coin: 4D4B2118-0435-439C-BA7C-99B9BD0DA7F4");
If you want to do anything with the specific coin, you'll need to forEach() in the callback:
snapshot.forEach(function(child) {
console.log("The coin has value: "+child.val());
})
Is there any reason why you can't store the coins by their uuid? It sounds like that is already a universally unique identifies; so if it is possible to store them with that key, the lookup would be a lot cheaper:
coinsRef.child("4D4B2118-0435-439C-BA7C-99B9BD0DA7F4")
.on('value', function(snapshot) {
console.log("The coin has value: "+snapshot.val());
})

Related

Not able to get key in nested data

I have created a realtime database in Firebase and have some data looking like this inside a key called "firms":
I got the user key and wants to find the key where the user is placed. I have tried something like this:
let userkey = 'the key that I have for the user'
ref.child('firms').child('users').orderByChild('user').equalTo('userkey').on("value",
function(snapshot) {
console.log(snapshot.val());
});
Is there something that i'm missing?
You have to do as follows:
ref
.child('firms')
.orderByChild('users/user')
.equalTo(userkey) // Warning: in your question you do equalTo('userkey') with quotes
.on('value', function (snapshot) {
console.log(Object.keys(snapshot.val())[0]);
});
As explained in the doc, you need to specify the relative path to the nested child in your orderByChild() call.

More direct method for updating fields in Firebase document without document ID?

The goal is to update a Firebase document.
The document ID is unknown at the time of updating. What is known is a property that acts as unique key on the document (email address in the case below).
Based on the official documentation and this answer, the code below works as a method for updating an array within the document.
This feels clunky, though.
Are there more direct methods for retrieving a reference to a single document and updating its fields?
// Set query.
let query = firebase.firestore().collection('users').where('emailAddress', '==', 'test#test.com');
// Run query.
try {
const querySnapshot = await query.get();
return querySnapshot.docs[0].ref.update({
designs: firebase.firestore.FieldValue.arrayUnion('foobar')
})
} catch(e) {
console.log('Error getting user: ', e);
}
No, what you're doing is the best you can do. If you don't know the ID, you have to query to find it. Firestore has no equivalent of a SQL "update where" command.

Firebase onSnapshot() listener... Can I somehow get data from before change

I have a collection in a firebase. I'm listening to changes with onSnapshot method.
If any item from a collection is changed in any way listener is fired. I am getting new data, which was inserted into my collection with docChanges method
db.collection('collection')
.onSnapshot((snapshot) => {
snapshot.docChanges().forEach((change) => {
const payload = {
id: change.doc.id,
data: change.doc.data(),
};
...... some action
});
});
and now... I need to compare new data (which was just inserted) with old data (from before insert) and I am wondering if there is any way to do that?
The Firestore SDK doesn't give you any ways to detect the differences between the "before" and "after" states of a document's fields. You will have to remember both snapshots and look for differences in the fields yourself. You might want to do a search for some ideas on how to go about this, for example: Generic deep diff between two objects

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".

JavaScript Firebase: Query Snapshot Always Null

No matter what I do I can't seem to figure out a way to access the child "onSite", which shows as being there when I log snapshot.val(), but I cannot figure out how to access it.
Code:
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
Here is the response:
It shouldn't be null, it should be false. I can't do child("4mUUjF...").child("onSite").val() because I don't know what the ID is before the query. Using an each loop doesn't work, it only loops through the first level, which is the ID.
Use the key of the object
Get the snapshot val and then find the key with the Object.keys method. This will allow you to then get inside the snap. Once there it's a simple matter of accessing the values like any other object.
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
let snap = snapshot.val();
let key = Object.keys(snap)[0]
console.log(snap[key].onSite);
})
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.
Your code needs to handle the list, by using Snapshot.forEach():
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID)
.once("value").then(function(result) {
result.forEach(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
});

Categories