$firebaseArray $indexFor() not finding key when given value - firebase

I have this firebase:
users: {
userId: {
notifications: {
notificationId: "Notification"
}
}
}
When given "Notification", I'm trying to find its notificationId (which is generated from the push() method) so I can eventually delete it. According to the docs, the $indexFor() method should do this for me. Here's my code:
var ref = new Firebase('https://url.firebaseio.com/');
$scope.dismissNotification = function(notification) {
var notificationRef = ref.child('users/' + $scope.currentUser.id + '/notifications');
var notifications = $firebaseArray(notificationRef);
notifications.$loaded().then(function(data) {
console.log(data);
console.log(data.$indexFor(notification));
}).catch(function(error) {
console.log('Error: ' + error);
});
};
The first log is the correct object with the notification string inside that I'm looking for, but the second log returns -1, when I want it to return the notificationId associated with it.

Not sure what you're trying to accomplish, but this is the simplest way to find the key for a given value:
var notificationRef = ref.child('users/' + $scope.currentUser.id + '/notifications');
var query = notificationRef.orderByValue().equalTo(notification);
query.once('child_added', function(snapshot) {
console.log(snapshot.key());
});

Related

firebase realtime database find node by child value

I have the following structure:
root
-LKMsdf2_Qxbwtv4238D
details
uid: john
-YKMWrmj_QxbwtvSBM5A
details
uid: tony
-R45Wrmj_Qxbf321BMd4
details
uid: karina
How can I find the ref key under 'root' by its uid:
e.g: by uid:karina I need to get the ref key -R45Wrmj_Qxbf321BMd4
is there a way to use some wildcard like /root/{recordid}/details/uid or something?
======== Thanks for the hints! ==== here is my final solution ================
findEntry = function(targetUid) {
var entriesRef = db.ref('root');
return entriesRef.once('value')
.then((snapshot)=>{
var id = []; // found id
snapshot.forEach((childSnapshot)=>{
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
var found = (childData.uid === targetUid);
if (found) {
console.log('Found for uid:' + targetUid + ': ' + childKey);
id = childKey;
}
return found; // true - breaks the forEach, false - continue
});
if (!id) {
console.log('Not Found for uid:' + targetUid);
}
return id;
});
}
No, the best you can do is child (key) search and equality (see the example here https://firebase.google.com/docs/reference/js/firebase.database.Query#equalTo)
// Find all dinosaurs whose height is exactly 25 meters.
var ref = firebase.database().ref("dinosaurs");
ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) {
console.log(snapshot.key);
});
There isn't a way to query deeper than that.
You could have other structures for reverse lookups, flatten out your data or solve it in a different way.

How to get a data from firestore while using batch?

I want to perform a batch transaction in firestore. I am storing last key in other collection.
i need to get the last key then increase by 1, then create two documents using this key. How can i do this?
let lastDealKeyRef = this.db.collection('counters').doc('dealCounter')
let dealsRef = this.db.collection('deals').doc(id)
let lastDealKey = batch.get(lastDealKeyRef) // here is the problem..
batch.set(dealsRef, dealData)
let contentRef = this.db.collection('contents').doc('deal' + id)
batch.set(contentRef, {'html': '<p>Hello World</p>' + lastDealKey })
batch.commit().then(function () {
console.log('done') })
If you want to read/write data in a single operation you should be using a transaction.
// Set up all references
let lastDealKeyRef = this.db.collection('counters').doc('dealCounter');
let dealsRef = this.db.collection('deals').doc(id);
let contentRef = this.db.collection('contents').doc('deal' + id);
// Begin a transaction
db.runTransaction(function(transaction) {
// Get the data you want to read
return transaction.get(lastDealKeyRef).then(function(lastDealDoc) {
let lastDealData = lastDealDoc.data();
// Set all data
let setDeals = transaction.set(dealsRef, dealData);
let setContent = transaction.set(contentRef, {'html': '<p>Hello World</p>' + lastDealKey });
// Return a promise
return Promise.all([setDeals, setContent]);
});
}).then(function() {
console.log("Transaction success.");
}).catch(function(err) {
console.error("Transaction failure: " + err);
});
You can read more about transactions and batches here:
https://firebase.google.com/docs/firestore/manage-data/transactions

Querying another easy table for push notification message

I have two easy tables configured in my Azure App backend:
Services with Id and ServiceName properties
ServiceDetails with Id, ServiceID and ServiceDetailDate properties
Whenever a new ServiceDetails entry is inserted, I want to send a message to my users via Push Notifications containing information about ServiceDetailDate and ServiceName.
So my question is how can I query another table to obtain information from it? In this case the ServiceID (from ServiceDetails table) is known, so I want to get the ServiceName from Services. Which code should I add to extract the ServiceName from the serviceInfo object (in the payload message) to my script to fulfill this request?
Actually I'm not sure about the query and serviceInfo instructions, so if I'm wrong with the code, don't hesitate to point me in the right direction.
var azureMobileApps = require('azure-mobile-apps'),
promises = require('azure-mobile-apps/src/utilities/promises'),
logger = require('azure-mobile-apps/src/logger'),
queries = require('azure-mobile-apps/src/query');
var table = azureMobileApps.table();
table.insert(function (context) {
var query = queries.create('Services');
var serviceInfo = query.where({'Id': context.item.ServiceID});
var payload = '{"messageParam": "Your service -service name- has been added on ' + context.item.ServiceDetailDate + '" }';
return context.execute()
.then(function (results) {
if (context.push) {
context.push.send(null, payload, function (error) {
if (error) {
logger.error('Error while sending push notification: ', error);
} else {
logger.info('Push notification sent successfully!');
}
});
}
return results;
})
.catch(function (error) {
logger.error('Error while running context.execute: ', error);
});
});
module.exports = table;
Thanks for your help.
You can use the following code to query another easy table in ServiceDetails.js.
table.insert(function (context) {
return context.tables('Services')
.where({ Id: context.item.ServiceID })
.select('ServiceName')
.read()
.then(function (data) {
var message = 'Your service ' + data[0].ServiceName + ' has been added on ' + context.item.ServiceDetailDate;
var payload = '{"messageParam": "' + message + '"}';
return context.execute().then(function (results) {
//..
});
});
});

Cloud Functions for Firebase - what is wrong with my code?

The following code executed when something is written at a certain location in the database.
What I expect from this code : If the number of coins are => 500 to subtract only once 500 coins from the current coins value and to add one ticket to the existing ticket value.
What I am getting in reality: The code recursively subtracts 500 coins until the coin value is lower than 500; It adds more tickets then it should.
Please , can somebody modify my code to work as expected ?
I do not know what I am doing wrong
exports.TransformCoinsIntoTickets1 = functions.database.ref('/AddTickets/{userid}').onWrite(event => {
var user = event.params.userid;
/// first get coins to see if we can lower coin value
var usercoinRef1 = admin.database().ref('coins').child(user);
usercoinRef1.on("value", function(snapshot) {
var numberofcoins = snapshot.val();
console.log("We are in snapshot of coins -> He has coins = " + numberofcoins);
if (numberofcoins >= 500 )
return usercoinRef1.set(numberofcoins-500).then(() => {
var ticketRef1 = admin.database().ref('tickets').child(user);
ticketRef1.on("value", function(snap123) {
var numberoftickets = snap123.val();
return ticketRef1.set(numberoftickets+1).then(() => {
console.log('Tickets Write succeeded!');
});
}, function (error) {
console.log("Error Tickets: " + error.code);
});
console.log('Coins Write succeeded!');
});
}, function (error) {
console.log("Error Coins: " + error.code);
});
//then we write the new coin value if we need to
});
I just realized that instead of
on
i should use
once
So, replacing
.on("value",
with
.once("value",
resolved the problem.

Firebase on(child_added) some field 'undefined'

I am working on a real time application and i am using firebase with pure html and javascript (not angularJS).
I am having a problem where i saved user's data to firebase with the given code by firebase :
var isNewUser = true;
ref.onAuth(function(authData) {
if (authData && isNewUser) {
authData['status'] = 'active';
authData['role'] = 'member';
ref.child("users").child(authData.uid).set(authData);
}
});
This will add the authData to the /users/ node. As you can see that i also appended some custom fields to the authData, status and role.
Now i am using this code to get the user's data from firebase and display them.
ref4.on("value", function(snapshot) {
var snapshotData = snapshot.val();
console.log('username: '+snapshotData.status);
});
If i use on('value'), the status get printed out on the console but if i do it this way,
ref4.on("child_added", function(snapshot) {
var snapshotData = snapshot.val();
console.log('status: '+snapshotData.status);
});
It is showing undefined for the status. May i know what's wrong and how to fix this problem. Thank you.
Since value is returning the path provided by ref4, and child_added is returning each child of that path, it's unlikely both are going to have a key status.
Consider this data structure:
{
"users": {
"brucelee": {
"status": "awesome"
},
"chucknorris": {
"status": "awesomerest"
}
}
}
If I now query for this according to your incomplete example:
var ref = new Firebase('https://<instance>firebaseio.com/users/brucelee');
ref.on('value', function(snap) {
// requests the brucelee record
console.log(snap.name(), ':', snap.val().status); // "brucelee: awesome"
});
ref.on('child_added', function(snap) {
// iterates children of the brucelee path (i.e. status)
console.log(snap.name(), ':', snap.val().status); // THROWS AN ERROR, because status is a string
});
So to do this on child_added with a data structure like this (and presumably somewhat like yours), it would look as follows:
ref.on('child_added', function(snap) {
// iterates children of the brucelee path (i.e. status)
console.log(snap.name(), ':', snap.val()); // "status: awesome"
});

Resources