0

I want to take datas from 2 different data collections and unite them under one class. My first collection's name is "Posts" and the other one is "UserDetails". I want to take "downloadUrl" and "comment" from Posts and "username" from UserDetails. But I can't do this. Here is my code:

class FeedsActivity : AppCompatActivity() {

    private lateinit var binding : ActivityFeedsBinding
    private lateinit var auth: FirebaseAuth
    private lateinit var db : FirebaseFirestore
    private lateinit var postArrayList : ArrayList<Post>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityFeedsBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        binding.recyclerView

        auth = Firebase.auth
        db = Firebase.firestore

        postArrayList = ArrayList<Post>()
        getData()


    }

    private fun getData(){
        db.collection("Posts").addSnapshotListener { value, error ->
            if(error != null){
                Toast.makeText(this,error.localizedMessage,Toast.LENGTH_LONG).show()
            }else{
                if(value != null){
                    if(!value.isEmpty){ //is not empty
                        val documents = value.documents
                        for(document in documents){
                            //casting
                            val comment = document.get("comment") as String
                            val downloadUrl = document.get("downloadUrl") as String
                            val post = Post(comment,downloadUrl)
                            postArrayList.add(post)



                        }
                    }
                }

            }
        }
        db.collection("UserDetails").addSnapshotListener { value, error ->
            if(error != null){
                Toast.makeText(this,error.localizedMessage,Toast.LENGTH_LONG).show()
            }else{
                if(value != null){
                    if(!value.isEmpty){ //is not empty
                        val documents = value.documents
                        for(document in documents){
                            //casting
                            val username = document.get("username") as String
                            val post = Post(username,comment,downloadUrl)
                            postArrayList.add(post)



                        }
                    }
                }

            }
        }


        }


How can I make this happen?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Check [this](https://stackoverflow.com/questions/69805908/firebase-query-to-fetch-data-from-two-nodes-together/69809023#69809023) out. It will help you solve the problem. – Alex Mamo Nov 07 '21 at 09:08

1 Answers1

0

I think the root cause of the confusion is that there’s no apparent way that a post from the Posts collection is related to a user from the UserDetails collection. In order to solve this problem, you would need to refactor your database. My suggestion is to add a userID field to each Post document, userID being related to a user from the UserDetails collection. In the UserDetails collection, the same userID should uniquely identify a user. You should review this related thread about how to design a Firestore database structure.

With these changes in mind, I rewrote your function to query the UserDetails collection with the userID that is present in the Post document. The matching username from the document in the query is used to create Post objects that go into the ArrayList.

 private fun getData(){
    db.collection("Posts").addSnapshotListener { value, error ->
        if(error != null){
            Toast.makeText(this,error.localizedMessage,Toast.LENGTH_LONG).show()
        }
        else{
            if(value != null){
                if(!value.isEmpty){ //is not empty
                    val documents = value.documents
                    for(document in documents){
                        //casting
                        val comment = document.get("comment") as String
                        val downloadUrl = document.get("downloadUrl") as String
                        //Getting the user ID from a post document
                        val userID = document.get("userID") as String
                        val userName: String
                        
                        //Querying the userDetails database searching for the matching userID
                        db.collection("userDetails").whereEqualTo("userID", userID).get()
                            .addOnSuccessListener { userDocs ->
                                for (doc in userDocs) {
                                    userName = doc.get("username") as String // Getting the username from the document
                                }
                            }
                        .addOnFailureListener { exception ->
                            Log.d(TAG, "get failed with ", exception)
                            }
                        val post = Post(comment,downloadUrl, userName)
                        postArrayList.add(post)
                    }
                }
            }
        }
    }
}

There is more information about how to build queries to Firestore in the documentation.

ErnestoC
  • 2,660
  • 1
  • 6
  • 19