My app loads links shared by a user on a listview. I'm trying to load 10-links/posts at a time, and once the user reaches the end query for 10 more links/posts, and so on.
I've denormalized the data, so that once a post is made, its created under "/links" and "user-links/$userId/" by the following code:
String key = mDatabase.child("links").push().getKey();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/links/" + key, postValues);
childUpdates.put("/user-links/" + FirebaseAuth.getInstance().getCurrentUser().getUid() + "/" + key, postValues);
Firebase Data
links
{
"pushId1": {
"userId" : YuPfsnJD, //userId1
"createdAt" : 1483309151261,
"link" : https://www.youtube.com/watch?v=bwbwTKXlvQA
},
"pushId2": {
"userId" : zZio89, //userId2
"createdAt" : 1483309145896,
"link" : https://firebase.google.com/docs/database/android/lists-of-data
},
"pushId3": {
"userId" : YuPfsnJD, //userId1
"createdAt" : 1483309155525,
"link" : https://firebase.google.com/docs/database/security/indexing-data
}
}
user-links
{
"userId1":
{
"pushId1":
{
"userId" : YuPfsnJD, //userId1
"createdAt" : 1483309151261,
"link" : https://www.youtube.com/watch?v=bwbwTKXlvQA
},
"pushId3":
{
"userId" : YuPfsnJD, //userId1
"createdAt" : 1483309155525,
"link" : https://firebase.google.com/docs/database/security/indexing-data
},
},
"userId2":
{
"pushId2":
{
"userId" : zZio89, //userId2
"createdAt" : 1483309145896,
"link" : https://firebase.google.com/docs/database/android/lists-of-data
},
},
}
This is how I currently retrieve the data based on the time its createdAt:
Query myTopPostsQuery = mDatabase
.child("user-link")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.orderByChild("createdAt")
.limitToFirst(QUERY_LIMIT);
Where; int QUERY_LIMIT = 10;
Firebase Rules
{
"rules":
{
".read": "auth != null",
".write": "auth != null"
}
}
Questions:
1) Once the user reaches the end, how do I skip the first 10 links (which have already been loaded) and load the next 10-links?
2) Is there a way to assign Ascending or Descending order? I would like to show the latest post first.
3) Is firebase-rules ".indexOf" the solution? If so can someone share the exact rule that I must write?
Note: createdAt is generated by the following code while creating the data initially: postValues.put("createdAt", ServerValue.TIMESTAMP );
Related
I want to retrieve data from the database and insert it into a recycleview.
The problem is that I don't know who I can get to the data inside the dataset.
First, take a look at my dataset structure: Json added below:
"Places" : {
"-M11-OIIHbKTVqCJ-Swv" : {
"name" : "Farmacia Pagani Dr. Roberto",
"others" : {
"01" : {
"Nome" : "Ambilify",
"Price" : 100
},
"02" : {
"Nome" : "Acetaminophoen",
"Price" : 120
}
}
},
"-M11-OJJCGAPdJUknLXX" : {
"name" : "FARMACIA DR. TUMIATTI MARIANO",
"others" : {
"01" : {
"Nome" : "Ambilify",
"Price" : 100
},
"02" : {
"Nome" : "Acetaminophen",
"Price" : 120
}
}
}
},
So what I want is: since I have the key "-M11-OIIHbKTVqCJ-Swv" I want to perform a search inside the object with this key. To do so I need to access Places/key object(-M11-OIIHbKTVqCJ-Swv)/others and then to perform a search based on Nome(means name in Italian). I want to return Nome: Ambilify Price : 100
This is what I did :
private void firebaseUserSearch(String searchText) {
DatabaseReference searchforData = FirebaseDatabase.getInstance().getReference("Places");
Toast.makeText(FirebaseSearch.this, "Started Search", Toast.LENGTH_LONG).show();
System.out.println("keyNameOfFarmacy"+keyNameOfFarmacy);
Query firebaseSearchQuery = searchforData.orderByChild(keyNameOfFarmacy).orderByChild("others").orderByChild("Nome").startAt(searchText).endAt(searchText + "\uf8ff");
FirebaseRecyclerAdapter<DataDetails, UsersViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<DataDetails, UsersViewHolder>(
DataDetails.class,
R.layout.list_layout,
UsersViewHolder.class,
firebaseSearchQuery
) {
#Override
protected void populateViewHolder(UsersViewHolder viewHolder, DataDetails model, int i) {
viewHolder.getDetails(model.getNome(), model.getPrice());
viewHolder.setDetails(model.getNome(), model.getPrice());
}
};
mResultList.setAdapter(firebaseRecyclerAdapter);
}
I have a problem with this part of the code because: orderByChild can be used just once.
Can anyone tell me how can I get the data please, I lost the last 2 3 h searching how to do it and I didn't find anything. Thank you in advance.
Change this:
Query firebaseSearchQuery = searchforData.orderByChild(keyNameOfFarmacy).orderByChild("others").orderByChild("Nome").startAt(searchText).endAt(searchText + "\uf8ff");
into this:
Query firebaseSearchQuery = searchforData.child(keyNameOfFarmacy).child("others").orderByChild("Nome").startAt(searchText).endAt(searchText + "\uf8ff");
You already have access to others and to the key so just use child for that and orderByChild for Nome.
I'm trying to add security rules to my firebase application. But auth.uid is not working..
Here is two of my security rules..
"groups": {
"$groupid":{
".read" : true,
".write" : "root.child('groupmembers').child($groupid).child('admins').child(root.child('users').child(auth.uid).child('username').val()).val()==true"
}
},
"groupchat":{
"$chatid":{
".read" : "root.child('groupmembers').child($chatid).child('members').child(root.child('users').child(auth.uid).child('username').val()).val()==true",
".write" : "root.child('groupmembers').child($chatid).child('members').child(root.child('users').child(auth.uid).child('username').val()).val()==true"
}
}
On the first rule auth.uid is working.. But in case of second and rest other rules, auth.uid is not working at all. I added my original uid in place of auth.uid and all rules are working properly.
Client side operation example..
Map<String, Object> map = new HashMap<String, Object>();
map.put("username", userid);
map.put("message", userid + " Created This Group.");
map.put("timestamp", ServerValue.TIMESTAMP);
map.put("zcode",chat_key);
map.put("type", "action");
FirebaseDatabase.getInstance().getReference()
.child('groupchat')
.child(groupid)
.push()
.updateChildren(map);
Users Structure
"users":{
"my_uid" : {
"email" : "example#gmail.com",
"username" : "user1"
}
}
groupmembers structure
"groupmembers":{
"groupid":{
{
"admins" : {
"user1" : true,
"user3" : true
},
"members" : {
"user1" : true,
"user2" : true,
"user3" : true,
"user4" : true
}
}
}
}
So how can I solve this problem?
I think it was because of the version mismatch or different packages used for it so it can't can the auth.uid
I am creating an android app and I am stuck at a problem. In order to explain the problem, I would like to show my database structure
{
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contacts" : {
"Contact1" : value (Contact number)
"Contact2" : value
"Contact3" : value
},
"name" : "Sagar Khan",
"phone" : 7276273667
},
"OLm7VWsMcGQpterECyhJ8YTSPna2" : {
"Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Sameer",
"phone" : 8412914728
},
"TXanCkqtB5PdEogtv8Dzw8y1ngw1" : {
""Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Harish",
"phone" : 7020743544
},
"qnDVoc72nXa8XvOH1L39VvqFzKL2" : {
"Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Harish Shinde"
"phone": 8149870822
}
}
This is very short structure the actual one is to big
Now what I want to do is I want to fetch only those users whose contact number is present in current user node and display those users in a Android list.
For example:
User 1 with id EXlzg1COUbOhQjwPCGbS1NRdp5H3 is having 3 contacts
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contacts" : {
"Sameer" : 8412914728 (Contact number)
"Contact2" : value
"Contact3" : value
},
"name" : "Sagar Khan",
"phone" : 7276273667
},
Now when I will fetch the list of users from my database and show it in my Android app list, I want only those users to be added whose contact number is present in User 1 contacts.
My problem is that I literally don't know how to do this as I am new to Android development and Firebase. I am clear with the read and write basics of Firebase, but such operations, I have no idea how to do it.
I have searched a lot, but cannot find any solutions or examples. A detailed description will be very good for me. ;) Thanks in advance.
Here's the change I propose:
This is the new database structure for Users node:
"Users" : {
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"name" : "Sagar Khan",
"phone" : 7276273667
},
..
}
And the contacts of the user "Sagar Khan" will be stored in another node called Contacts under that user's UserID (EXlzg1COUbOhQjwPCGbS1NRdp5H3) :
"Contacts" : {
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contact1":{
"name" : "Sameer",
"phone" : 7276273000
},
"Contact2":{
"name" : "Alice",
"phone" : 7276273600
},
...
},
//other user id with their contacts
...
}
I suspect that the user ID (eg: EXlzg1COUbOhQjwPCGbS1NRdp5H3) is taken from a logged in user, using:
mAuth.getCurrentUser().getUid();
Therefore, to get the contacts of a logged in user you can query the database like this:
DatabaseReference mUserContactsRef = FirebaseDatabase.getInstance().getReference().child("Contacts").child(mAuth.getCurrentUser().getUid(););
mUserContactsRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot userContact : dataSnapshot.getChildren()){
Contact contact = userContact.getValue(Contact.class);
//add each contact to an arraylist and use it to populate a list of contacts
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You can add each contact object to an ArrayList and use it to populate a list. The key is the User ID, you can access anything related to a user using the UserID.
This is the approach I recommend and what I have used in the past successfully for similar scenarios.
This question already has answers here:
How do you prevent duplicate user properties in Firebase?
(2 answers)
Closed 6 years ago.
I am adding username for my Chat App to Firebase Database successfully.
I implemented in activity:
FirebaseDatabase firedb = FirebaseDatabase.getInstance();
in createUser Method.
private void createUser(String uname){
Map<String,Object> newUser = new HashMap<String, Object>();
newUser.put("uname",uname);
DatabaseReference dbref = firedb.getReference();
dbref.child("Users").push().setValue(newUser);
}
When user click a button this method works. This method work correctly but I want to make uname primary key. I do not want to add a username if it is alerady exists.
Database Structure:
Rules:
{
"rules": {
".read": true,
".write": true
}
}
Finally, how to prevent duplicated uname ?
You have to add a top level /uname/ Node. Your data will be like this for example :
{
"Users" : {
"user1" : {
"uname" : "value1",
},
"user2" : {
"uname" : "value2",
},
"user3" : {
"uname" : "value3",
},
},
"uname" : {
"value1": "user1",
"value2": "user2",
"value3": "user3",
}
}
Now you have to Enforce New Data Structure:
{
"rules": {
"users": {
"uname": {
".validate": "!root.child('uname').child(newData.val()).exists()"
},
}
}
}
I have a child node that looks like this:
and I want to get the data and put the userID in the from of array. So that I can iterate and write data in those userID. However currently I am unable to figure out how to read from the database and get the userID into an array.
I only want the userID in the array. Where the node is like (friends/"key"/userID).
here is the json -
"friends" : {
"-KVFPNlR76oIsnvdeuEr" : {
"userID" : "QbfjBiy7yhTT9Bi9H8dLNv7h0A02",
"userName" : "michael s speed",
"userPhoto" : ""
},
"-KVFPNmS42zrefrGKM2L" : {
"userID" : "QbfjBiy7yhTT9Bi9H8dLNv7h0A02",
"userName" : "michael s speed",
"userPhoto" : ""
},
"-KVQWEH4xY1-88vyUmKd" : {
"userID" : "ZEBXY8WmQaWIza4L2ptSPpKUQGY2",
"userName" : "michael dinesh",
"userPhoto" : ""
},
"-KVVeqLtEji4b1ZW3gcj" : {
"userID" : "Hvf69rGDTsgQgBLdnUcg5uGZSgB2",
"userName" : "rina bora",
"userPhoto" : ""
}
},