The goal is : after a user has been logged in , the next activity should display his list of courses.
There is a table of courses in Parse's cloud, but how can I retrieve the correct courses (current user's courses) ?
I've thought of 2 approaches :
1. using getCurrentUser method - but what if there are more than one user in the cache ?
2. save for each course the userName that saved it , and then query for that userName - but how should I know that the currentUser method will return the correct user ?
How can I solve this problem ?
using getCurrentUser method - but what if there are more than one user in the cache ?
There's always one currently logged in user and ParseUser.getCurrentUser() will get it. Well, unless there is no logged in user.
but how should I know that the currentUser method will return the correct user
As above. I don't get what you're confused about.
There is a table of courses in Parse's cloud, but how can I retrieve the correct courses (current user's courses)
and
save for each course the userName that saved it , and then query for that userName - but how should I know that the currentUser method will return the correct user ?
I can think of two approaches here. There may be more. Up to you what you decide to use.
So you have the _User table and the Course table. You can do one of the following:
Add a courses array to each _User and for each _User, store their list of courses there. It should be a list of objectIds, so basically you'll have the ID's of all the courses that _User is registered for. Each Parse object has a limited size in the database so you should use it if you are sure you won't need big amounts of data for each user. If you want to retrieve this, query the _User table by the id of the user and fetch the list of courses.
The "relational" approach: add an UserCourse table that has a userId and a courseId column. Every time you want to add a course for a particular user, you add a new entry in here that holds the id of that user and the id o the course. Similarly to the above, have a query that fetches all the stuff from UserCourse by userId. Note that in this case you'll also need to make sure your query fetches the data from _User and Course. Otherwise you'll just end up with UserCourse entries, which merely store ID's.
Related
So suppose I am building an app that lets users manage trips. When a trip is created , any number of users can be added in it. I want this data to be stored in a single place and then for each user be able to retrieve the trips that that person is included in. My data looks like this:
-trips
-<trip-id>
-title
-budget
-etc
-people
-<person-id>
-name
-uid
-<person-id>
-name
-uid
-<trip-id>
-
-
-
This trip will contain all the trips created by all the users. To show any person their trips, I want to retrieve only the lists that person exists in.
This is what I've tried to do including other similar approaches.
rootReference.child("trips").orderByChild("uid").equalTo(FirebaseAuth.instance.currentUser.uid).addValueEventListener(object:ValueEventListener){
override fun onDataChange(snapshot: DataSnapshot) {
//this should only return the trips that current user exists in.
}
}
I have checked the documentation for searching and filtering on firebase but there is nothing that show filtering based nested keys. One particular example is this. I understand it perfectly. If for example I try to filter my trips based on the main attributes like title, budget, it works, but not when I use an attribute of a nested child.
What other approach can I use to filter based to nested keys or should I structure the data differently? Any help is greatly appreciated.
Firebase Realtime Database queries operate on a flat list of child nodes directly under the path that you query.
So the value you order/filter on has to be at a fixex path under each immediate child node. Since that isn't the case for your uid, you can't query across all trips for the UID of all users of those trips.
You can query across one trip for a UID of a user (and then get back that user), or you can query across all trips for properties of the trip itself, such as its title or budget.
If you want to query across all users on all trips, consider keeping an additional list where you have the UID of the user as the key, and then all their trips under there:
"user_trips": {
"uid1": {
"tripid1": true,
"tripid2": true
},
"uid2": {
"tripid2": true,
"tripid3": true
}
}
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value
Many to Many relationship in Firebase
In your opinion, is better to use the random ID auto generated by firebase for a new document or it's not a bad practice if I choose the name of the document so that I can perform easier query?
For example, instead of searching inside the collection "users" in all the random id document, and then search for a user with the field "email = test#gmail.com", should I assign to my document the title "test#gmail.com" and then search on the collection "users" for the document with the name "test#gmail.com"?
What do you think?
This is difficult to answer because you're asking for an opinion about your database structure when we have no concept of your use case.
However, let me throw out a couple of thoughts.
if I choose the name of the document so that I can perform easier
query
The key name is not related nor has anything to do with the child data it contains as far as a query goes. take a look
users
-Y89j9kksd0kskd //a users uid for example
email: "thing#test.com"
-y9099k,msp,sps
email: "dude#thing.com"
If you want to query for an email of "dude#thing.com", the query 'ignores' each child key (-Y89... -y90... etc) and looks at the email: node within.
If you name the keys and do a query, it still makes no difference, it still ignores that key. It is returned as the key property of the snapshot but that's not the issue here since we know the value is the email of the email: child.
users
-thing#test.com
email: "thing#test.com"
-dude#thing.com
email: "dude#thing.com"
The issue here is that . cannot be used in key names so now you have to encode/decode every key. That's a lot of extra code.
More importantly, if the email address changes, you will have to change every occurrence of that email address in ALL of your data. And since you can't change keys, you would have to delete every node and re-write it. Ugh.
Using the first example is the way to go. You can keep a reference to that user throughout the app (using the uid for example) and no matter what child data changes within that node (email for example), the rest of the data remains unaffected.
There is a but here... there's always a but.
Sometimes you may want to know if a piece of data exists at specific path - in those cases, you can access it directly. For example
users
-Y89j9kksd0kskd //a users uid for example
email: "thing#test.com"
things_i_like
food:
pizza: true
taco: true
color:
blue: true
wine:
ornellaia: true
Suppose I have this users uid of -Y89j9kksd0kskd and I want to see if pizza is a food they like. Instead of querying the food node I can access it directly at
/uid/things_i_like/food/pizza
and see if the value is true (or see if it exists)
or to see if they like the wonderful Italian Ornellaia wine, test for true (or existance) at
/uid/things_i_like/wine/ornellaia
As you can see, leveraging the uid or Firebase created keys at a top level doesn't affect your queries but when you know you want to access a specific datapoint within a known node, naming the node keys is one solution.
It's all a balance and depends on what kind of queries you want to run... If you wanted to know all users that like pizza, that would be a query (and a slightly different structure) so you wouldn't know the specific path and a query would be needed.
My Firebase Database tree
I am trying to query for the "lastMessageKey" field stored under the lastMessage branch in Firebase Database.
Problems :
1) "lastMessage" branch has a child "7KSk3TO58UZQd7KewlC2eNhdMj92" this is the current user id so, I can fetch it but below this is another child "other User's userId" just the parent of "lastMessageKey" field. And I want to order the Query by the lastMessageKey value's creation time. But I donot know the other userIds in the query, so I am unable to use orderByChild("lastMessageKey").
2) Note : lastMessageKey value is a pushKey generated by push(), so we can get it's creation time as said in - 1).
chatsQuery = mRootRef.child("lastMessage").child(mCurrent_user_id).orderByChild("lastMessageKey");
Here I didnot require to pass the child between the current userid and the lastMessageKey ie.the other userIds. I was directly able to jump to "lastMessageKey" value ordering upon providing the start path with child("mCurrent_user_id"). And this solved,my problem.
I am using Parse for one of my android application and struggling for a query to get output.
Application Parse DB has three table which is as described below-
User: user related information with unique object Id
Post: Contains Post related information with unique object Id and UserId(Pointer to user table) who create the post
Like: UserId(Pointer to user table) represent who is Liking the post, PostId(Pointer to post table) which post is liking and unique
object Id
Now I want to make a single compound query for All post for a specific user along-with total number of likes to corresponding post. Please suggest a solution/query for that
When a user creates a post, assign the user objectID to some post identifier property in the post table.
To retrieve all posts from a user, a query like this may help:
query.whereEqualTo("objectID", currentUser.objectID)
If you're just concerned about the like count, rather than each user who has liked the post, you may want to have an Integer value in the post table that is incremented after a user presses the like button on that post.
You should create your own webHook.
Following this exemples here you can easily learn and develop your own stuff, you can even add some triggers to your application!
https://parse.com/docs/cloudcode/guide#cloud-code-cloud-functions
https://parse.com/docs/cloudcode/guide#cloud-code-beforesave-triggers
If User table doesn't have Post<.Relation> column
I suggest you to read about how to join queries.
f.g. make a query1 to get the user, then another query2 to get all posts with whereMatchesQuery('UserColumnInPostTable', query1) function.
Now, you are going to get all posts of a specific user efficiently.
.
If User table have Post<.Relation> column
this is the easiest way
Just get the user object and get the relation object, then get the query, and find in background
I am making an Android app that will use a friends list. As far as I know, you can't store an array in a MySQL table, so it seems that I will have to make a separate table from my "Users" table and call it, say, "Friends". This table will just have Friend1 and Friend2.
My question is the preferred way to store this table. I can use the UserName field (string) from my "Users" table to store them, or I could use the UserID field (integer) from my "Users" table. Using the ID would make the table smaller because the small integers take up more space than the string, but at the same time, I access this data mainly using the UserName field (so I have to query the Users table to get the UserID from the Users table).
Which method is preferred for a MySQL table? Using the users name directly so I do not have to find the UserID from the Users table, or saving the table as two integers, and querying to find the ID from the UserName? Thanks.
Store two userID keys from the users table.
Let's say that you change a name of a contact from "Guy from bar" to "Mr. McMoneypants". If this contact was a friend, it will still show up as "Guy from bar" even after the change.
Try to keep data from living in multiple places.
The preferred method is to use the UserID from the Users table in the Friends table as a way to reference that user. That way, as Phillip says, the User can change their name and you only have to change it in one place. Plus, as you say, your Friends table will take up less space with a numeric column as compared to a string column.
And in regards to "(so I have to query the Users table to get the UserID from the Users table)", the following query is not too cumbersome:
SELECT FriendName
FROM Users Natural Left Join Friends
WHERE UserName = 'Ralph';
As far as your query is concerned, you never had to deal with the UserID column.
That's not that much harder than your method:
SELECT FriendName
FROM Friends
WHERE UserName = 'Ralph';