I'm using this query to fetch the posts by user A and sort by timestamp.
This below query fetches the posts by user A but it doesn't sort by date.
mDatabase = FirebaseDatabase.getInstance().getReference("posts");
String UID = "userA";
Query myTopPostsQuery = mDatabase.equalTo(UID).orderByChild("UID");
I tried using below query, but it returns an empty set.
Query myTopPostsQuery = mDatabase.equalTo(UID).orderByChild("date");
What is the right way to achieve my result?
This is my Data Structure:
posts
-KlgYXK01ezPjk
UID: "YiXgM3qgqcsd"
date: 1496428200000
post: "This is a Test Post by user A"
,
-KlgYXK01ezPpl
UID: "YiXgM3qgqcsd"
date: 1496428220022
post: "This is another Test Post by user A"
,
-KlgYXK01ezKjk
UID: "YiXCWsdj712"
date: 1496428203000
post: "This is a Test Post by user B"
,
Well this may not be the exact answer you are expecting but it helps when your app scales up.
I recommend you use a fan out data structure.
By this create a separate node user-posts where you store all the posts by individual users like below:
user-posts
-YiXgM3qgqcsd //this us A's UID
KlgYXK01ezPjket4ery62
post: "This is a Test Post by user A"
date: 1496428200000
author:'A'
KlgYXK01ezPjket4ery62
post: "This is a 2nd Test Post by user A"
date: 1496428500000
author:'A'
KlgYXK01ezPjket4ery62
post: "This is a 3rd Test Post by user A"
date: 1496428600000
author:'A'
-YiXCWsdj712 //this us B's UID
KlgYXK01ezPjket4ery62
post: "This is a Test Post by user B"
date: 1496428200000
author:'B'
Now you can query for A's posts lik this:
mDatabase = FirebaseDatabase.getInstance().getReference("user-posts");
String UID = "userA";
Query myTopPostsQuery = mDatabase.child(UID).limitToLast(10);
Since pushing data into a node creates a unique key which are by default in chronological order you don't have to worry about sorting by timeline as you are using limitToLast() which gives you posts from the bottom i.e latest
So its better you push data to different nodes posts and user-posts whenever a user creates a post. This is better as writing data is cheap in firebase as compared to reading data
Now you can just pull out data from ref "user-posts/UID" instead of firebase querying data fromposts filtering all the posts by user A then again ordering by timeline which will be expensive and slow if you have many number of posts
When it comes to pushing data to different nodes i.e posts and user-posts this could be cheap and you can use updateChildren() method like below:
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// Generate a new push ID for the new post
Firebase newPostRef = ref.child("posts").push();
String newPostKey = newPostRef.getKey();
// Create the data we want to update
Map newPost = new HashMap();
newPost.put("title", "New Post");
newPost.put("content", "Here is my new post!");
Map updatedUserData = new HashMap();
updatedUserData.put("user-posts/" + newPostKey, true);
updatedUserData.put("posts/" + newPostKey, newPost);
// Do a deep-path update
ref.updateChildren(updatedUserData, new Firebase.CompletionListener() {
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
System.out.println("Error updating data: " + firebaseError.getMessage());
}
}
});
You could refer to the firebase blog post here
Related
I am working on an app using Firebase Database. In my Firebase Database I have a node like xxxxxx_yyyyyy, where xxxxxx represents first user ID and yyyyyy represents second user ID. Now I want to retrieve only nodes which contains xxxxxx_ from my database. I don't know how to do this. Because all I know is Firebase gives only equalsTo() method.
There is no query like contain(). I recommend to change node structure (locating yyyyy under xxxxx).
There Is no Query Like Contains in Fire base.!
if you dnt want to change structure of your node you can Store Data in list and then simply use list.contains() you will get your desired Result.!
HtBVbQP0qMSrCStroYsIiMSuhMC3 //node userID
Name:XXXXXXX
You can get this Data by using orderbychild(XXXXXX);
There is no contain() method, however, you can solve this problem in two ways:
Using the split() method from String class.
Using Regex Pattern
Here is the code:
String firebaseField = "xxxxxx_yyyyyy";
String[] data = firebaseField.split("_");
System.out.print("Using split method: ");
for(String part : data) {
if (part.equals("xxxxxx")) {
System.out.print(part + " ");
//Add your logic
}
}
Or
System.out.print("\nUsing Regex Pattern: ");
Pattern datePattern = Pattern.compile("_");
data = datePattern.split(firebaseField);
for(String part : data) {
if (part.equals("xxxxxx")) {
System.out.print(part + " ");
//Add your logic
}
}
Hope it helps.
I want to add some certain data to a Firebase as arrays. Example:
groups : ['a','b','c']
How can I add and read data in Firebase from Android?
When you have a structure like that, you actually shouldn't be using an array to model it. It seems much more like a set in my eyes.
In the Firebase Database sets are best modeled as keys, since that automatically guarantees that items are unique. So your structure then becomes:
groups: {
"a": true,
"b": true,
"c": true
}
The true values are just markers, since Firebase won't allow you to store keys without a value.
Now to add a group to this, you'd use Firebase's setValue() function:
DatabaseReference root = FirebaseDatabase.getInstance().reference();
DatabaseReference groupsRef = root.child("groups");
groupsRef.child("d").setValue(true);
From the documentation:
setValue() - Record or change exists values
If you want to only append datas, you can to use updateChildren().
In Java, if we know that the data is array-like, it can be cast as a List:
Firebase julieRef = new Firebase("https://SampleChat.firebaseIO-demo.com/users/julie/");
julieRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
GenericTypeIndicator<List<String>> t = new GenericTypeIndicator?<List<String>>() {};
List messages = snapshot.getValue(t);
if( messages === null ) {
System.out.println('No messages');
}
else {
System.out.println("The first message is: " + messages.get(0) );
}
}
// onCancelled...
});
Check this best practices post from the Firebase Blog.
/users:
- user1
- name: user1name
- /contacts
- user2
- user3
.....
- user2
- name: user2name
....
This is my current firebase database. When user1 is logged in I check which contacts he has and get their UIDs. Now that I have their UIDs I'm trying to read the names of his contacts. How can I get the names for each of his contacts? Do I have to read the entire /users directory or can I use a query that retrieves only the data that I want. (In this case: the name of user2 and user3)
You'd do a nested read. So retrieve /users/$uid/contacts, then loop over the keys in there and for each key load /users/$key.
Supposing that you already have the user selected, you can go about it in two ways:
1) Use .child(String user); in your database reference.
2) You may have declared a URL for your database. Add + "/" + String user; to your URL.
You can further use these ways to parse through contacts of that user.
Finally, to retrieve contacts, you have to loop through.
Here is an example code:
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot msgSnapshot : snapshot.getChildren()) {
mDataset.add(msgSnapshot.getKey());
mAdapter.notifyDataSetChanged();
}
}
This snippet fetches data and adds it to your adapter (which can be used to populate list view, grid view etc)
I have a database in Firebase for Android and I have an object with the attributes you see in the image. An object is stored in the database with the following code:
FirebaseUser user = mAuth.getCurrentUser();
String videoId = getIntent().getStringExtra("VIDEO_ID");
minuto = player.getCurrentTimeMillis();
Watching watching = new Watching(user.getUid(), videoId, String.valueOf(minuto));
DatabaseReference mRef = database.getReference().child("Watching").push();
mRef.setValue(watching);
The problem I have is as I am using push() to store the nodes I am having duplicate data as you can see in the image.
Is there any way to avoid storing duplicate data? Knowing that I don't have my own ID to store.
Any help ?
It depends on how you define a duplicate.
A common case where people have this question is when they're storing users. There the definition of a duplicate is simple: if two user objects have the same value for uid, they're the same user. So in that case you should store the users under their uid, instead of under a push ID.
The same applies for your situation. If a single user can only watch a single video, store the nodes under Watching by the uid of the user:
Watching
"NX7...A33"
"idVideo": "b13...o4s"
"minute": "0"
But if it's the combination of uid + idVideo that is unique, store the nodes under a combined key:
Watching
"NX7...A33_b13...o4s": "0"
Now you can easily prevent duplicates, by using setValue() instead of push():
String key = user.getUid() + "_" + videoId;
ref.child("Watching").child(key).setValue(String.valueOf(minuto));
I was facing same problem like you and this is how i figure it out. I m checking email address that user entered with the one saved in my db.if any match found then show toast that email already exists otherwise save with new key.
mFirebaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
//If email exists then toast shows else store the data on new key
if (!data.getValue(User.class).getEmail().equals(email)) {
mFirebaseDatabase.child(mFirebaseDatabase.push().getKey()).setValue(new User(name, email));
} else {
Toast.makeText(ChatListActivity.this, "E-mail already exists.", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(final DatabaseError databaseError) {
}
});
Let's say I have this JSON tree:
"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter","lastName":"Jones"}
]
How can I do this in Firebase? Every time I create an object under "employees", with the name "firstname", it replaces the previous object with "Firstname".
I previously used Parse's tables, but since it's been taken down, then I need help learning this confusing thing.
I'm using Android.
Firebase databases have no native support for lists or arrays. If we try to store an list or an array, it really gets stored as an "object" with integers as the key names (see doc).
// we send this
['hello', 'world']
// Firebase databases store this
{0: 'hello', 1: 'world'}
In this way your tree in firebase would look like this:
{"employees":{
0:{"firstName":"John", "lastName":"Doe"},
1:{"firstName":"Anna", "lastName":"Smith"},
2:{"firstName":"Peter","lastName":"Jones"}
}
}
Using Firebase terminology we can say that node emloyees has three child nodes with IDs 0,1,2 respectively.
But saving data with integer IDs in Firebase is not recommended (see this to know why). Firebase provides a push() function that generates a unique ID every time a new child is added to the specified Firebase reference.
Here is an example from Firebase Android doc.:
//create firebase ref using your firebase url
Firebase ref = new Firebase("https://docs-examples.firebaseio.com/android/saving-data/fireblog");
Firebase postRef = ref.child("posts");
Map<String, String> post1 = new HashMap<String, String>();
post1.put("author", "gracehop");
post1.put("title", "Announcing COBOL, a New Programming Language");
postRef.push().setValue(post1);
Map<String, String> post2 = new HashMap<String, String>();
post2.put("author", "alanisawesome");
post2.put("title", "The Turing Machine");
postRef.push().setValue(post2);
And as a result in posts node we will have two childs with autogenerated ids:
{
"posts": {
"-JRHTHaIs-jNPLXOQivY": {
"author": "gracehop",
"title": "Announcing COBOL, a New Programming Language"
},
"-JRHTHaKuITFIhnj02kE": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}
You're probably looking for DatabaseReference.push(), which creates a new child under the location.
var employeesRef = mDatabase.child("employees");
var newEmployeeRef = employeesRef.push()
newEmployeeRef.setValue(employee);
The best place to read more about this is in the section on appending data to a list in the Firebase documentation.