Hierarchical (Firebase) Database Structure, 'Posts/User', or 'Users/Posts'? - firebase

I am trying to build a structure that allows users to access only their own posts.
I have two possible ways in mind, and I'm not sure either of them is best practice. My end goal is to allow a user to read and write to all of their own posts only.
Approach A - Posts/Users (Not sure this can work from a security standpoint)
{
"posts" : {
"001" : {
"text" : "note 1",
"userID" : "user1"
},
"002" : {
"text" : "note 2",
"userID" : "user1"
},
"003" : {
"text" : "note 3",
"userID" : "user2"
}
}
}
Approach B - Users/Posts (Not as flat as Approach A)
{
"users" : {
"user1" : {
"posts" : {
"001" : {
"text" : "note 1",
},
"002" : {
"text" : "note 2",
},
}
},
"user2" : {
"posts" : {
"003" : {
"text" : "note 3",
},
},
}
}
I'm trying to follow the guidelines to keep data flat. In reality the post items will have more than just text, but not extend more than 2 levels deep. Thanks for any advice you can give!

I would have
{
"Users": {
"user1uniqueRef": {
"postIDUniqueRef1": {
"text" : "Here is someText"
"imageURL" : "https:// etc etc etc"
"postIDUniqueRef2": {
"text" : "Here is someText"
"imageURL" : "https:// etc etc etc"
"user2uniqueRef": {
"postIDUniqueRef1": {
"text" : "Here is someText"
"imageURL" : "https:// etc etc etc"
}
}
}

Related

How to orderByChild in nested Child in angularfire?

My firebase database structure is as below. I would like to search with a particular "Info/Email", let's say "abc#abc.com".
{
"-KhWrBcYyMluJbK7QpnK" : {
"Info" : {
"Email" : "xyz#gmail.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Pending"
}
}
}
I added a rule too
"Invitation" : {
".indexOn": ["Info/Email","Settings/Status"]
}
My AngularFire code is as follows:
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.child("Info").orderByChild("Email").equalTo("abc#abc.com");
var allInvitations = $firebaseArray(userInvitations);
But I am getting a FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "Email" at /Invitation/Info to your security rules for better performance. and of course I am not receiving any data.
What are the mistakes I made here? Also can I add multiple orderByChild, for example: if I want to find details of the record, which has "Info/Email" equal to "abc#abc.com" and "Settings/Status" equal to "Pending" ?
The Firebase API only allows you to filter children one level deep
So with reference to your data structure:
if it were to be this way,
{
"-KhWrBcYyMluJbK7QpnK" : {
"Email" : "xyz#gmail.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Pending"
}
}
}
You should write your rules this way instead.
"Invitation" : {
"Info" : {
".indexOn": "Email",
},
"Settings" : {
".indexOn": "Status",
}
}
Then you will be able to query the data
var allInvitations = [];
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.orderByChild("Email").equalTo("abc#abc.com");
userInvitations.on('value', snap => {
var invitations = snap.val()
for (prop in invitations ) {
allInvitations.push(invitations[prop ]);
}
console.log(allInvitations);
})

Loading mapbox with Firebase database

I'm trying to learn Firebase and Mapbox and wanted to integrate the two. Firebase stores some of my data in the following format:
{
"messages" : {
"-KUE2EwfvbI48Azw01Hv" : {
"geometry" : {
"coordinates" : [ 28.6618976, 77.22739580000007 ],
"type" : "Point"
},
"properties" : {
"description" : "xyz",
"hashtag" : "#xyz",
"imageUrl" : "xyz.jpg",
"name" : "Xyz Xyz",
"photoUrl" : "xyz.jpg",
"title" : "XYZ"
},
"type" : "Issue"
},
"-KUD2EwfvbI48Azw01Hv" : {
"geometry" : {
"coordinates" : [ 12.9715987, 77.59456269999998 ],
"type" : "Point"
},
"properties" : {
"description" : "xyz",
"hashtag" : "#xyz",
"imageUrl" : "xyz.jpg",
"name" : "Xyz Xyz",
"photoUrl" : "xyz.jpg",
"title" : "XYZ"
},
"type" : "Issue"
}
}
}
Is there a way to load the data and plot it into Mapbox? The examples require a GeoJSON file hosted somewhere that can be used to plot them. How can we use the Firebase database to plot on the Mapbox in realtime?
Sorry if my question is ambiguous. I'm willing to provide more information if needed :D
Thanks!
You can load the data, but you first have to convert it to a valid GeoJSON object.
Here is a JSFiddle using the data you provided:
https://jsfiddle.net/mkrv9uuy/
var firebaseGeojsonFeatures = [];
for (var key in firebaseData.messages) {
var f = firebaseData.messages[key];
f.type = "Feature";
firebaseGeojsonFeatures.push(f);
}

My structure in Firebase db. Is that proper hierarchy?

I would like to constract proper structure for an app which shows a list of companies. When I tap on one company, the app shows phone numbers in other view. Could somebody advise me with my structure?
{
"companies" : {
"c1" : {
"name" : "Secure Home LLP",
"subject" : "Security"
}
},
"phones" : {
"c1" : {
"p1" : {
"name" : "Check point",
"phone" : "201-478-4600"
},
"p2" : {
"name" : "Dispatcher",
"phone" : "201-478-4678"
}
}
}
}
The structure that you have given will be a great tiring work while parsing into the different data.
This following structure will be a better Option. You can parse into the phone numbers just by getting into the company keys. Here it is c1, c1
{
"companies" : {
"c1" : {
"name" : "Secure Home LLP",
"subject" : "Security",
"p1" : {
"name" : "Check point",
"phone" : "201-478-4600"
},
},
"c2" : {
"name": "neCompanyName",
"subject" : "Design",
"p2" : {
"name" : "Dispatcher",
"phone" : "201-478-4678"
}
}
}
}

why json which is shown in browser and exported is different in firebase

The problem is, the json data structure can be different than shown in browser when you export it.
The structure I have:
{
"name" : "Main Category",
"prio" : "10",
"subCategories" : {
"subCategory1" : {
"name" : "Sub Category 1",
"products" : {
"product1" : true
}
},
"subCategory2" : {
"name" : "Sub Category 2",
"products" : {
"product2" : true
}
}
}
}
If subCategories field has more than one child, data structure does not change. But, if it has only one child, here is the result:
{
"name" : "Main Category",
"prio" : "10",
"subCategories" : [ null, {
"name" : "Sub Category 1",
"prio" : 1,
"products" : {
"product1" : true
}
} ]
}
Why does it change?

Meteor.users.find().fetch() returns single user

I am using accounts-google package to register users
I have multiple users stored in mongo
db.users.find()
{ "_id" : "av8Dxwkf5BC59fzQN", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:34:52.195Z"), "hashedToken" : "8na48dlKQdTnmPEvvxBrWOm3FQcWFnDE0VnGfL4hlhM=" } ] } } }
{ "_id" : "6YJKb7umMs2ycHCPx", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:35:00.185Z"), "hashedToken" : "d/vnEQMRlc4VI8pXcYmBvB+MqQLAFfAKsKksjCXapfM=" } ] } } }
But Meteor.users.find().fetch() returns document for logged in user only - shouldn't this return entire collection? Are the other users somehow private by default?
This is the default behaviour. You can only see who you're logged in as.
You can make a custom publish function to publish a custom subset/what you want. In the example below I publish all the users (only the profile field)
Server side code
Meteor.publish('users', function() {
return Meteor.users.find({}, {fields:{profile: true}});
});
Client side code
Meteor.subscribe("users");
You might want to alter these to only publish what is relevant to the user. If you have over 100 users this begins to get wasteful to publish all of them to the client.

Resources