Firebase getting data from database - firebase

so my database is as follows
Program1
Posts:
PostsID1:
Name: John
Age: 12
User_Id: nv4h8fh4uen8h8f4ufn
PostsID2
Name: Don
......
I have the user Id for the user, how can i check if that user has post in the database and if he does just return his post rather than all the posts.
For example // nv4h8fh4uen8h8f4ufn is user id.. he has a post so it will return John, 12,

I dont know if I understood right but, the most common is use the users id as a key, and with that generate child keys for his posts, like this:
Users:
nv4h8fh4uen8h8f4ufn1:
Name: John
Age: 12
Posts:
idPost1:
postData
idPost2:
postData

Related

GORM creates duplicates on many2many

I am using GORM in my Go Gin API and want to create an association between my User and the Role table. So far, I have simply followed the documentation, but I am running into a problem.
Here are my used models:
type User struct {
gorm.Model
FirstName string
LastName string
Email string `gorm:"unique"`
Password []byte
Roles []Role `gorm:"many2many:user_roles"`
}
type Role struct {
gorm.Model
Name string
}
While I'm still developing, I want to write data directly to the database when I start the API. For this I create the following:
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon#doe.local",
Password: encoded,
Roles: []Role{
{Name: "admin"},
{Name: "service"},
},
})
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon2#doe.local",
Password: encoded,
Roles: []Role{
{Name: "admin"},
{Name: "service"},
},})
This way I want each name to appear only once in the role table. The corresponding ID should be used in the automatically created user_roles table each time such an entry is created.
What happens, however, is this:
Roles Table:
id
name
1
admin
2
service
3
admin
4
service
User_Role Table:
user_id
role_id
1
1
1
2
2
3
2
4
I have read through https://gorm.io/docs/associations.html and tried Omit but nothing worked yet.
I hope someone has an idea or already solved the same problem. Thanks a lot!
Edit:
When trying "try sending just the role IDs instead of role names" i do it like this:
Db.Create(&User{
FirstName:"Jon",
LastName:"Doe",
Email: "jon2#doe.local",
Password: encoded,
Roles: []Role{
{ID: 1},
{ID: 2},
},})
This gives me the error
cannot use promoted field Model.ID in struct literal of type Role
2. Edit
The ID needs to be listed seperated in the Role model, it does not work just with the gorm.Model
type Role struct {
gorm.Model
ID uint `gorm:"primarykey"`
Name string
}

NoSQL data integrity (Firebase + Redux)

I saw the following code from one of the firebase example apps (Link):
// 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;
When you add a new post, it writes the same data object into two different places. This seemed odd to me because it means now there are two exactly same data that you have to take care of if you want to update or delete them. I'd rather do something like this:
post: {
id: 1,
username: 'awesomeMan', // store necessary author's metadata
title: 'hello',
body: 'body
}
author: {
id: 1,
username: 'awesomeMan',
email: 'hello#gmail.com',
posts: {
1: true // index posts by their ids
}
}
If I do it this way, I still have a bit of data duplicate because I store user's metadata username inside a post. But isn't it better than having two exactly same data in two places?
Edit: Follow Up Question
I want to add Comments resource to Posts. Given these two options, which one is better, and why?
Option 1.
Store all comments related to postId under this path:
/post-comments/${postId}
This is the only path for comments and we don't store anything into comments/
Option 2.
Store comments in comments/ and index them by ids in posts.
/post/${postId}/comments #only consists of commentIds that belong to this post
/comments/${commentId}

Meteor: Join by userId but display username, publishing user data?

So, I have bunch of collections joined with Meteor.users collection by userId as foreign key. E.g. I have Posts collection and each post has its own page. On a post page I have userId as author and a bunch of comments(from Comments collection) on that post each has postId and userId. UserIds are ugly, instead I would like to display usernames. How would you achieve that? Any smart package that I can use or working example? I don't like the idea of publishing all users data. Thank you.
You don't need to publish all data. In publish method you can use fields specifier in that way:
Meteor.users.find({}, {fields: {'username': 1}});
That way you have only _id and username published.
Then in meteor helper you can have:
username: function() {
var user = Meteor.user.findOne(this.userId);
return user.username || user.profile.name;
}
if Post is your context

handling complex queries in firebase

I'm developing a shopping cart mobile application using ionic framework and FIREBASE as back-end . I have a requirement that I need to join JOIN, SORT, FILTER and PAGINATE by multiple data attributes.
Sample data structure is given below.
products : {
prod1:{
name: Samsung-s4,
type: pro,
category: Phone,
created_datetime: 1426472828282,
user: user1,
price: 400
},
prod2:{
name: iPhone 5s,
type: pro,
category: Phone,
created_datetime: 1426472635846,
user: user2,
price: 500
},
prod3:{
name: HP Laptop i3,
type: regular,
category: Computer,
created_datetime: 1426472111111,
user: user1,
price: 600
}
}
user_profiles : {
user1:{
name: abc_user,
display_name: ABC,
email: abc#mail.com
},
user2:{
name: xyz_user,
display_name: XYZ,
email: xyz#mail.com
}
}
I need to query the products using multiple ways. two simple examples given below.
1) Get all products with Pagination, where type is "pro" then join with user_profiles and SORT by created date.
2) Get all products with Pagination, filter by category then join with user_profiles and SORT by created date.
Like above there will be more and more filtering options coming in Eg: price.
My main problem is, I couldn't find straight forward way of doing this using FIREBASE query options. Also I referred firebase util documentation but there also I don't see a way of getting this done.
As far as I see only way to get this done is, do the majority of processing in client end by getting all the data (or majority of the data) in to client side and do the SORT / FILTER / PAGINATE in client end.
But we are expecting thousands of records in these schemas, therefore there will be a huge performance impact if we do the processing in client end !!
Appreciate your expertise/support to solve this problem.
Thank you in advance.
UPDATE:
I changed the data structure (as webduvet explained) and tried with firebase-util but failed to achieve what i want. CRITERIA :Products -> Filter By type/pro -> Sort By products.created_date
type: {
pro:{
product1: user1,
product3: user1,
...
},
regular:{
...
}
}
firebase-util - angularfire code
var list = $firebase(new Firebase.util.NormalizedCollection(
ref.child("products").orderByChild('created_datetime'),
ref.child('type').child('pro')
).select(
{key: "products.name" , alias: 'name'}
).ref()).$asArray();
"products" will have hundred thousand records, so we have to make sure we restrict as much possible in firebase end rather than handling in client end.
Please help !
This has to be done not by queries but by database design. You need to store data in de-normalised way for example:
type: {
pro:{
product1: user1,
product3: user1,
...
},
regular:{
...
}
}
the above structure will give you option to query all pro products and retrieve the user id as well. Firebase offer good sorting mechanism so there should not be a problem. The more complex query you require the more complex the data structure will be needed and the more denormalized data you will have.
But as pointed out by #Swordfish0321 sql type of db might suit you much better after all.

Choosing a KEY for an object store

O., this may be a relatively simple question, but it's one that I couldn't figure out (both by testing code and googling).
I have Simple Login with Email/Password enabled, and so when they login, the email used will be converted into a md5_hash.
I've created a "Users" object store, which currently looks like this:
users
|____ Bob
|__ md5_hash: 8120jf283
|__ username: Bob
|____ Alice
|__ md5_hash: 2938njv29
|__ username: Alice
|____ Chris
|__ md5_hash: 230948mv2
|__ username: Chris
My question is: How can I change the "schema" so that it stores the users by their md5_hash, instead of by their username? You can see above that it's storing the users by Bob, Alice, and Chris. It would work better for me if I could store them by their md5_hash so that it would like something like this:
Users
|___ 02938492
|__ md5_hash: 02938492
|__ username: Bob
Here's the code that I'm using to create a user and $save it into the Firebase database:
var ref = new Firebase(FIREBASE_URL + 'users');
var users = $firebase(ref);
function(authUser, username) {
users[username] = {
md5_hash: authUser.md5_hash,
username: username,
$priority: authUser.uid
};
users.$save(username).then(function() {
*do something here in callback*
});
I've tried 2 different things that didn't work. I tried using
users[authUser.md5_hash] = {...};
and I also tried
users.$save(authUser.md5_hash)
Neither of these work. Nothing gets saved to the Firebase database. It's perplexing to me because I'm almost 100% sure that it's one of those 2 parts that determines how the key is saved to firebase, but it doesn't do anything.
ULTIMATELY, what I'm trying to do is be able to "grab" the username value after a person logs in. I will be displaying their username on a navbar in a kind of "welcome Bob" fashion. However, when a user logs in, there is not yet any correlation between their md5_hash and their username. I have to be able to grab the username from the "users" table, and because I don't know their username, and the "users" table is currently indexed or keyed by their username, I have no way to get it...
A quick design question as well (if you have time):
Also, this doesn't have to do with the above question, but it's somewhat related. Just a quick question about designing my firebase "schema". If you have time, it'd be great if you could take a quick read below:
As I mentioned before, I'm using Simple Login with email/password. When a user logs in, I have access to the md5_hash of their email. Thus, to associate other user information with that login, I've created the "User table". I'm trying to connect the Login/Authentication with the said table using the md5_hash (because this is unique to each user), and then store other useful user data in it such as username, age, etc.
Is this how one would design their firebase schema? I'm used to using some sort of GUID or index in SQL, and I figured that since an md5_hash is unique, I could similarly use it to "index" my firebase users table. I just don't know if doing it this way will cause some problems in the future.
Thank you very much for your time. Any help or advice on this would be much appreciated! :)
With Simple Login, the user is created with a unique id:
var fbRef = new Firebase(URL);
var auth = new FirebaseSimpleLogin(fbRef);
auth.createUser(email, password, function(error, user) {
if( error ) throw error;
console.log('unique id', user.uid);
});
You can utilize that for your unique identifier. If that is insufficient, you can obtain a unique ID from the Firebase push() command:
var fbRef = new Firebase(URL);
var uniqueId = fbRef.push().name();
fbRef.child('users/'+fbRef).set(userData);
// or even shorter
var uniqueId = fbRef.push(userData).name();
With AngularFire, you can simply call $add instead of $save to create unique ids:
var users = $firebase(fbRef);
users.$add( userData ).then(function(ref) {
console.log('unique id', ref.name());
});

Resources