Retrieve Value in Firebase for Web App - JavaScript - javascript

I'm currently in the proccess of making a web application for a university project and I need some help in retrieving a value in the Firebase database. Here is the structure:
What im trying to do is see if a specific uid is present anywhere unfer the ref 'addresses'
this is my code:
var refAdd = firebase.database().ref().child('addresses');
refAdd.orderByChild("uid").equalTo(user.uid).once("value", function(snapshot){
console.log("(snapshot) request found for " + snapshot.key);
snapshot.forEach(function(child) {
console.log("request found for " + child.key);
});
});
So what I'm trying to do here is see if ther current user UID is present under 'addresses', if it is then log the push key value where it's located.
Anyone one have any idea on how to go about it?

The best approach would probably be to denormalize your data. That means that each time you write a "request" for a specific user under a specific "addresses" item you should also write, in another database node the "push" id of the "address" under the uid of the user.
In other words, based on your example you should have a database like:
- addresses
+ -LAPf7dNDU...
+ requests
- ......
- addressesByUid
- 9nras7IY..... //You use the user uid as the key of this node
- adressId: "-LAPf7dNDU..." //The key of the address
In such a way your query will be much easier.
The only "difficulty"is the fact that you have to maintain the two nodes in sync. But this can be easily done with e.g. an set of writes like in the following example (from the doc):
// Get a key for a new Post.
var newPostKey = firebase.database().ref().child('posts').push().key;
// Write the new post's data simultaneously in the posts list and the user's post list.
var updates = {};
updates['/posts/' + newPostKey] = postData;
updates['/user-posts/' + uid + '/' + newPostKey] = postData;
return firebase.database().ref().update(updates);
Finally, note that, if necessary, you could have several addressIDs under a user uid by doing something like
- addressesByUid
+ 9nras7IY..... //You use the user uid as the key of this node
- -LAPf7dNDU...: "true"
- -LUTTE66hf...: "true"

Related

read data from childByAutoId in node.js

I am trying to read data from firebase that is saved by childByAutoId(). I can successfully read the top half, but the reads what the childByAutoId() is. for example.
and in my firebase functions is
the logger -- uid is BoSwank... is correct, however on the line below for
logger -- workerId is -MBauxL.... is incorrect. That is the value of the childByAutoID() and it should be hkKplzF...
How I am trying to read this data is below.
exports.observeNotifications = functions.database.ref('/notifications/{cardUID}/{workerId}').onCreate((snapshot, context) => {
var uid = context.params.cardUID;
var workerId = context.params.workerId;
console.log('LOGGER --- uid is ' + uid);
console.log('LOGGER --- workerId is ' + workerId)
})
I thought changing
/notifications/{cardUID}/{workerId} to /notifications/{cardUID}/{cardUID/workerId}
and then changing
var workerId = context.params.workerId;
to
var workerId = context.params.cardUID.workerId;
would do the trick but it does not.
With Cloud Functions database triggers, the wildcards in the path only match the names of nodes. They never match the values of any children. What you are seeing right now is the expected behavior, and there's no way to change it.
If you want the value of children under the location that was matched in the path, you're going to have to reach into it using the snapshot parameter that was passed to the function. It is a DataSnapshot object, and contains all of the values of all of the children under the location that was matched in the path.
In your case, the value of workerId is going to be found like this:
const workerId = snapshot.val().workerId
I suggest reading over the documentation for more complete information about how database triggers work.

Querying firebase database to retrieve user name

I am working on firebase for the first time. I am confused in querying the database. I have two objects on the database, one is the Auth and second one is the Chats. In Auths I have number of UID(user id) nodes, each of these nodes have their respective username. What I am trying to do is, I want to query that Auth object and get all the usernames which is equal to the one I take from a user through input box. In my sql it will be simple as SELECT * FROM auth WHERE username = userInputValue. I need same query like this, Below is what I have done so far.
var _firbaseDB = firebase.database(),
_firebaseAuthRef = _firbaseDB.ref("Auth/");
$("body").on("submit",".search-from",function(e){
e.preventDefault();
var ev = e.target,
_allUsers = $(ev).serializeArray()
_user = _allUsers[0].value;
_firebaseAuthRef.equalTo(_user).on("child_added",function(res){
console.log(res.val());
})
})
You were almost there. What's missing is that you need to specify which attribute you're querying on:
_firebaseAuthRef.orderByChild("n").equalTo(_user).on("child_‌​added",function(res)‌​{
console.log(res.val());
})
More info on the Firebase Database Documentation.

Check and Increment the Version Number of an IndexedDB.

I have an IndexedDB that is storing a large amount of dynamic data. (The static data is already cached by a Service Worker)
My problem is as this data is dynamic, I need the IndexedDB to be cleared and it to be restored each time the application is opened. For this, I need the version number to be incremented so that the onupgradeneeded event is fired. I can't think of any logical way to do this, and even using the following call in the onupgradeneeded event I get an undefined answer.
e.target.result.oldversion
My IndexedDB code is as follows, with the parameteres being:
Key - The name of the JSON object to store in the database.
Value - The JSON object itself.
function dbInit(key, value) {
// Open (or create) the database
var open = indexedDB.open("MyDatabase", 1);
console.log(value);
// Create the schema
open.onupgradeneeded = function(e) {
console.log("Old Version: " + e.target.result.oldversion); //Undefined
console.log("New Version: " + e.target.result.newversion); //Undefined
var db = open.result;
var store = db.createObjectStore("Inspections", {keyPath: "id", autoIncrement: true});
var index = store.createIndex(key, key);
};
open.onsuccess = function() {
// Start a new transaction
var db = open.result;
var tx = db.transaction("Inspections", "readwrite");
var store = tx.objectStore("Inspections");
var index = store.index(key);
store.add(value);
// Close the db when the transaction is done
tx.oncomplete = function() {
db.close();
};
}
}
As this method is called several times for several 'Key' objects, I will need to work out a way to increment this Version number once per opening of the page, and then move the 'add' call to outside of the onupgradeneeded method - but for the moment the priority is making sure it runs through once - incrementing the version number, firing the onupgradeneeded, deleting the current data, storing the new data.
Thanks in advance!
The oldVersion and newVersion properties (note the capitalization) are on the IDBVersionChangeEvent, not on the IDBDatabase. In other words, this:
console.log("Old Version: " + e.target.result.oldversion); //Undefined
console.log("New Version: " + e.target.result.newversion); //Undefined
should be:
console.log("Old Version: " + e.oldVersion);
console.log("New Version: " + e.newVersion);
Now that said... you're using the schema versioning in a somewhat atypical way. If you really want to start with a fresh database each time the page is opened, just delete before opening:
indexedDB.deleteDatabase("MyDatabase");
var open = indexedDB.open("MyDatabase", 1);
// An open/delete requests are always processed in the order they
// are made, so the open will wait for the delete to run.
Note that the queued operations (delete and open) would then be blocked if another tab was holding an open connection and didn't respond to a versionchange event sent out in response to the delete request. Maybe that's a good thing in your case - it would prevent two tabs from partying on the database simultaneously.
A more typical usage pattern would be to only change the version when the web app is upgraded and the database schema is different. If you did need to wipe the data across sessions you'd do that on open, rather than on upgrade, and use things like clear() on the object store. But now we're getting into the design of your app, which it sounds like you've got a good handle on.

get method not working on Parse current User

I am making an express app with Parse. In my cloud code, I am trying to get an attribute of the current user, but it is returning me undefined. My code looks like following:
app.get('/home/subscriptions',function(req,res){
Parse.Cloud.useMasterKey();
var user = Parse.User.current();
var ifstud = user.get("isStudent");
console.log('student: ' + ifstud); // undefined
console.log('id: ' + user.id); // OK. works fine.
}
I am able to retrieve the id of the user as above but not able to call the get method on user. In their API reference, they have mentioned that Parse.User.current() returns a Parse.Object, so I think in user I have _User object and I should be able to call all methods supported by a Parse.Object.
What might be the issue here?
Thanks
I figured it out and putting this answer for future reference to users who visit this question.
The Parse.User.current() returns only a pointer to the user and not the complete user object. To get access to all fields of the user, fetch the entire object using the fetch method.
var fullUser;
Parse.User.current.fetch().then(user){
fullUser = user;
}).then(function(){
// Place your code here
});
I think it should be: var ifstud = Parse.User.get("isStudent");

Best way to manage Chat channels in Firebase

In my main page I have a list of users and i'd like to choose and open a channel to chat with one of them.
I am thinking if use the id is the best way and control an access of a channel like USERID1-USERID2.
But of course, user 2 can open the same channel too, so I'd like to find something more easy to control.
Please, if you want to help me, give me an example in javascript using a firebase url/array.
Thank you!
A common way to handle such 1:1 chat rooms is to generate the room URL based on the user ids. As you already mention, a problem with this is that either user can initiate the chat and in both cases they should end up in the same room.
You can solve this by ordering the user ids lexicographically in the compound key. For example with user names, instead of ids:
var user1 = "Frank"; // UID of user 1
var user2 = "Eusthace"; // UID of user 2
var roomName = 'chat_'+(user1<user2 ? user1+'_'+user2 : user2+'_'+user1);
console.log(user1+', '+user2+' => '+ roomName);
user1 = "Eusthace";
user2 = "Frank";
var roomName = 'chat_'+(user1<user2 ? user1+'_'+user2 : user2+'_'+user1);
console.log(user1+', '+user2+' => '+ roomName);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
A common follow-up questions seems to be how to show a list of chat rooms for the current user. The above code does not address that. As is common in NoSQL databases, you need to augment your data model to allow this use-case. If you want to show a list of chat rooms for the current user, you should model your data to allow that. The easiest way to do this is to add a list of chat rooms for each user to the data model:
"userChatrooms" : {
"Frank" : {
"Eusthace_Frank": true
},
"Eusthace" : {
"Eusthace_Frank": true
}
}
If you're worried about the length of the keys, you can consider using a hash codes of the combined UIDs instead of the full UIDs.
This last JSON structure above then also helps to secure access to the room, as you can write your security rules to only allow users access for whom the room is listed under their userChatrooms node:
{
"rules": {
"chatrooms": {
"$chatroomid": {
".read": "
root.child('userChatrooms').child(auth.uid).child(chatroomid).exists()
"
}
}
}
}
In a typical database schema each Channel / ChatGroup has its own node with unique $key (created by Firebase). It shouldn't matter which user opened the channel first but once the node (& corresponding $key) is created, you can just use that as channel id.
Hashing / MD5 strategy of course is other way to do it but then you also have to store that "route" info as well as $key on the same node - which is duplication IMO (unless Im missing something).
We decided on hashing users uid's, which means you can look up any existing conversation,if you know the other persons uid.
Each conversation also stores a list of the uids for their security rules, so even if you can guess the hash, you are protected.
Hashing with js-sha256 module worked for me with directions of Frank van Puffelen and Eduard.
import SHA256 from 'crypto-js/sha256'
let agentId = 312
let userId = 567
let chatHash = SHA256('agent:' + agentId + '_user:' + userId)

Categories

Resources