SQL like joins in Firestore

喜夏-厌秋 提交于 2021-02-10 22:41:06

问题


I have a collection called creditcards and a collection called ownedcreditcards in Cloud Firestore. I want to perform a query where I JOIN the two collections to find only the creditcards that exists in the creditcards-collection, and not in the ownedcreditcards. From my understanding SQL like JOINS does not exist in Firestore, and you have to retrieve the data in multiple queries. I am trying to call the getAll()-functions (which retrieves all the documents) on both my collections, temporarily store the data in two ArrayLists, and then compare the two lists with each other. But my attempts of storing the data in an ArrayList has been unsuccessful, as it returns empty when I try to LOG it.
How can I store the data from both my collections in an ArrayList, or is there an easier way of doing this?

creditcards-collection with the following fields:

  • id
  • name
  • provider

creditcards-collection

ownedcreditcards-collection with the following fields:

  • id
  • creditcardid
  • creditcardname
  • nickname
  • userid

ownedcreditcards-collection


The code for my Activityand Store-classes are more or less identical for both usercreditcard and creditcard. Below is the code for the usercreditcard.

UserCreditCardActivity.kt

val arrayList = ArrayList<Any>()

    private fun retrieveCards() {
    val userCreditcard = UserCardStore()
    userCreditcard.getAll(object : Callback<UserCardModel> {
        override fun onCallback(list: List<UserCardModel>) {
            for (card in list) {
                adapter.add(UserCardItem(card)) //this works
                arrayList.add(card) //this doesnt work as when I print the list it returns empty
            }
        }
    })
}

UserCardStore.kt

    override fun getAll(myCallback: Callback<UserCardModel>) {
    auth = FirebaseAuth.getInstance()
    documentdata.whereIn("userid", listOf(auth.uid))
       .get().addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val list = ArrayList<UserCardModel>()
            for (document in task.result!!) {
                val usercard = document.toObject(UserCardModel::class.java)
                list.add(usercard)
            }
            myCallback.onCallback(list)
        }
    }
}

回答1:


From my understanding SQL like JOINS does not exist in Firestore, and you have to retrieve the data in multiple queries.

Yes, that's correct, a "JOIN" type operation is not supported by Cloud Firestore. A Firestore query can only get documents from a single collection at a time. If you need to get data from both collections and add the results to a list, you'll have to perform two different queries.

The key to solving this problem is to attempt to get the results of the second query only when the first query completes. In code, these queries should look like this:

creditcardsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            List<UserCardModel> userCardList = new ArrayList<>();
            for (QueryDocumentSnapshot document : task.getResult()) {
                userCardList.add(document.toObject(UserCardModel.class));

                ownedcreditcardsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot doc : task.getResult()) {
                                userCardList.add(doc.toObject(UserCardModel.class));
                            }

                            //Do what you need to do with the list
                        } else {
                            Log.d(TAG, "Error getting documents: ", task.getException());
                        }
                    }
                });
            }
        } else {
            Log.d(TAG, "Error getting documents: ", task.getException());
        }
    }
});

However, this approach might be considered a little bit expensive since you always read the content of both collections. A possible alternative you have is to introduce a third collection with data already "joined" from both collections. This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database. It's for Firebase Realtime Database, but the same rules apply to Cloud Firestore.



来源:https://stackoverflow.com/questions/63632614/sql-like-joins-in-firestore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!