Cannot retrieve any values using equalTo() query Firebase - android

I'm building a chat app and this is what my Database looks like:
So, I currently have a users node as well as a chats node.
The users node saves the last last login date and the chats Ids that the user is currently part of. In the chats node, it is saved the User Ids that make part of the conversation as well as the messages which have an Id, Content, Send Date, and User who sent.
Currently I am building the activity where it is displayed the conversations that the user is part of (using a recyclerview).
To be able to know what conversations the user is part of, instead of retrieving all conversations, I retrieve the chats ids that are in the user node and I put them all in an ArrayList<String>.
The code that retrieves those Ids and puts them in the ArrayList is this:
db.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach{
chatsId.add(it.key.toString()) // ChatsId is the ArrayList<String>
}
getChats2()
}
})
And this code works like a charm.
The problem comes when I try to query the chats node just to retrieve the chat that has the value equal to the values retrieved in the code above.
** That code is implemented in the getsChat2() **:
db = FirebaseDatabase.getInstance().getReference("chats")
// For each chatId, queries the DB to find the chat reference
chatsId.forEach {
val query = db.equalTo(it)
query.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {it2->
println("Do something")
// Do something with the chat reference
}
}
})
}
The problem is, even if there is a node with the same value as the chatsId variable, the println("Do Something) never actually prints.

It's a bit hard to understand what you're trying to do, but my educated guess is that you're missing an orderByKey() call:
val query = db.orderByKey().equalTo(it)
When you don't call any orderBy...() method, the nodes are sorted on their priority. That's a left-over from the early days of the API that has very little practical use, so these days it mostly means that you must call orderBy...() before filtering.

Related

How to get data based on userId from firebase Android kotlin?

I am trying to fetch data from firebase based on userId, when the user logged in I need to show his profile details based on its id but I am unable to fetch it. Any help?
auth = FirebaseAuth.getInstance()
databaseRef = FirebaseDatabase.getInstance().getReference("Users/")
databaseRef.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
//I want first_name and all other details of users
Log.e("first_name", snapshot.child(uid).getValue(String::class.java))
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
One problem is that you don't seem to initialize uid anywhere. So that should be:
auth = FirebaseAuth.getInstance()
uid = auth.currentUser.uid
Also see the Firebase documentation on getting the current user.
Next is not necessarily a bug, but definitely an optimization you'll want to do. Right now you read the entire Users node into your Android app, to then only get a value from /Users/$uid. As you add more users to the database, this is not going to scale.
What you'll want to do instead, is only load the node for the current user from the database with:
databaseRef = FirebaseDatabase.getInstance().getReference("Users/")
var userRef = databaseRef.child(uid)
userRef.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
Log.e("first_name", snapshot.getValue(String::class.java))
}
...

how to get some child list from Firebase android kotlin?

How i can read just color item in the image with out all data sub child?
I try this
val database = FirebaseDatabase.getInstance()
val personalDataReference = database.getReference("user personal data")
val messageList = ArrayList<String>()
personalDataReference.addValueEventListener(object : ValueEventListener{
override fun onDataChange(dataSnapshot: DataSnapshot){
messageList.add(dataSnapshot.value.toString())
}
override fun onCancelled(error: DatabaseError) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException())
}
})
but it get all the data
Consider using the Firebase Kotlin SDK by GitLive.
This library is also multi-platform, so the same code can be used on both Android and on iOS via Kotlin Multiplatform Mobile.
The code to read the keys from Firebase realtime database would look like this:
val keys = db.reference("/path/to/user personal data")
.valueEvents
.first()
.children
.mapNotNull { it.key }
Note here that valueEvents is a Kotlin Flow of DataSnapshot, therefore you can do more than simply taking the first snapshot and mapping it to a list as shown above. See the Flow documentation.
The things you've marked yellow are known as keys in Firebase terms.
To get a list of only the keys, you can do:
personalDataReference.addValueEventListener(object : ValueEventListener{
override fun onDataChange(dataSnapshot: DataSnapshot){
for (childSnapshot in dataSnapshot.children) {
messageList.add(childSnapshot.key)
}
}
Note that this will still read all JSON from the database, but the list will only contain the keys.

How can I get data from firebase to data model?

I'm quite new at Kotlin. I have data class which hold image urls named testModel. I need to add data to model from firebase with that code:
Here my data model: class testModel(val imageLinks: List<String>)
private val dbRef = FirebaseDatabase.getInstance().reference.child("categories").child("1").child("top")
fun readDataFromFirebase(){
dbRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
var list = ArrayList<testModel>()
for (e in dataSnapshot.children){
println(e.value)
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.e("DB", "loadPost:onCancelled", databaseError.toException())
}
})
}
Actually this block can get value from firebase I can see in run console my image urls but I can't add these on my testModel. How can I make it? Also I need good tutorials for these kind of works, like data models, read and write data with Kotlin. I am waiting for your advice.
PS: I already tried getValue method but is give error java.lang.
In your dataclass, change List<String> with ArrayList<String>, because the type List<E> does not exist in firebase, but arrays do.
Save your data as an Array<String> in firebase and then when you retrieve your snapshot, do snapshot.toObject(TestModel::class)

Get random user from Firebase

I'm working on an application in kotlin for sending an image to a random user or to multiple user from firebase. My database is structured like this :
Users
bVk3KBL81AY2LUVUbC6G1qcLAcl2
username : test
uid : bVk3KBL81AY2LUVUbC6G1qcLAcl2
And I don't know how to get a random user from firebase, I searched but I don't find the best solution for my structure.
I try with this post : How to get unique random product in node Firebase?
But the code doesn't work I have multiple errors
Thank you in advance to any one who may be able to give me some solutions.
Edit #1
I've worked on it and it's working, but I don't know how limit the random to 3 users for example.
In my application the user can change the limit of user so I need to change the random limit.
My code :
fun chooseRandomUser() {
val rootRef = FirebaseDatabase.getInstance().getReference()
val productsRef = rootRef.child("users")
val valueEventListener: ValueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val productList = ArrayList<String?>()
for (ds in dataSnapshot.children) {
val name = ds.child("username").getValue(String::class.java)
productList.add(name)
Log.d("FragmentActivity", "usernames : $name")
}
val productListSize = productList.size
val randomProductList = ArrayList<kotlin.Int>()
randomProductList.add(Random().nextInt(productListSize))
Log.d("FragmentActivity", "list : $randomProductList")
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("FragmentActivity", "Error: ${databaseError.message}")
}
}
productsRef.addListenerForSingleValueEvent(valueEventListener)
}
As far as I could understand, you want to pick a random user from all the list of users that you have in your firebase database. You can simply do that on the android side.
I think you already know how to get all the users from the firebase database. Store the users in a list. Then I would try to come up with a random function which could give me an index of the list randomly and I could pick that user from the list based on that random index.
The same implementation can go for selecting multiple users from that list as well.
I hope that helps.

Firebase real_time database query doesn't work

I'm using Firebase real-time database in my Android project. My database scheme as below :
I want to get best 10 scores. My query :
val query = reference.child("users").orderByChild("score").limitToFirst(10)
query.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(dataSnapshot: DataSnapshot) {
dataSnapshot.children.forEach {
val score: String = it.child(Constants.scoreKey).value as String
Log.i(TAG,"score:"+score)
}
}
})
I hope to see best 10 scores on logcat. But it didn't. I see random scores.
What is my mistake ?
In order to solve this, change the type of your score field from String to int or long, otherwise the order is done lexicographically.
There is no operator in Firebase and as far as i know nor in other databases that allow you to change this behavior. Instead, you will need to modify the data to get the behavior you want. If you want to go with the String value, store the values that are in the order you need them when sorted lexicographically. For numbers you can accomplish that by padding them with zeroes:
As an example:
"0131" //zero added before
"0132" //zero added before
......
"1308"
"1309"
"1310"
"1311"

Categories

Resources