0

Im trying to calculating some data together . What I have is a videos collection and then each video has a doc id and and then some field for example the uid of the user that uploads this video. And also every video has a sub collection named uservotes. Inside their I saved user voting of this video. This is how It looks

enter image description here

enter image description here

enter image description here

And what I want is getting of one user the user votes rating field calculating together . HERes how I get for one video the rating maybe that will help to understand

FutureBuilder(
                                      future: firebase,
                                      builder:
                                          (BuildContext context, snapshot) {
                                        if (snapshot.connectionState ==
                                            ConnectionState.waiting) {
                                          return Center(
                                              child: Text("loading..."));
                                        } else {
                                          double summe = 0.0;
                                          final docs = snapshot.data.docs;

                                          for (int i = 0;
                                              i < docs.length;
                                              i++) {
                                            summe += (docs[i]['rating']);
                                            print(summe);
                                          }
                                          final possiblestars = docs.length * 5;
                                          print(possiblestars);

                                          return Text(
                                            "${summe.toInt()}/${possiblestars}",
                                            style: TextStyle(
                                                color: Colors.white,
                                                fontWeight: FontWeight.bold,
                                                fontSize: 18),
                                          );
                                        }
                                      }),

The firebase stream is this one

   var firebase = FirebaseFirestore.instance
                      .collection('videos')
                      .doc(videos.data()['id'])
                      .collection('uservotes')
                      .get();

So instead of getting all user votes of one video I wanna get all uservotes of all videos form the same user. You can see that each video in videos collection has uid field and thats the uid of the user that upload the video I can get the current user id with that

  final uid=   FirebaseAuth.instance.currentUser.uid;

And every video that has saved this uid as uid value Iinside field "uid" in videoscollction is one off the videos that I needed . Then I wanna get of each video the sub collection uservotes all rating to calculating they together . Dont get confused about the same uid doc inside user votes collection thats because the user that uploads this current video also rate his own video . Hope anyone can help .

2 Answers2

0

Unfortunately, it's impossible in a single query. You should get all videos firstly and then make a new call for each one to get subcollection.

Jan Rozenbajgier
  • 534
  • 4
  • 13
0

For your requirement, with your data model, you would need to query all the videos docs with the same uid, and then, for each doc, query all the doc of the uservotes subcollection.

You could simplify this queries by adding the video owner uid to the uservotes docs and use a collectionGroup query.

HOWEVER, it is not recommended at all to query an entire (sub)collection each time you want to get the number of documents, because you are billed for each document that you read. So it can very fast generate an important bill...

You should maintain a counter for each user (and maybe for each video?). For that the best is to use distributed counters. I would advise to use Cloud Functions to update the counters, this way end-users cannot modify the counters.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • Is there maybe an easier way maybe I should saved the user votes collection data not like I do at the moment maybe in a own collection ? –  May 02 '21 at 12:10
  • You would still have to query an entire (sub)collection each time you want to get the number of documents in it. Your choice depends on the number of docs you expect in the collections and... on the amount of money you have on your bank account ;-) – Renaud Tarnec May 02 '21 at 12:25
  • What if I do something like this FirebaseFirestore.instance .collection('uservotes') .doc(uid) .collection("videos") .doc(id) .set({'videoid': id, 'rating': _rating, 'uid': uid}); –  May 02 '21 at 12:33
  • See my comment above. – Renaud Tarnec May 02 '21 at 12:35
  • But why I should then ave to query an entire (sub)collection. I can get the data with FirebaseFirestore.instance .collection('uservotes') .doc(uid) and then just do a query I dont understand why you saying I have to query an entire subcolletion –  May 02 '21 at 12:37
  • My above comment is valid for collections or for subcollections. If you need to query a collection each time you want to get the number of documents you are going to pay for each read. This is valid for collections or for subcollections. – Renaud Tarnec May 02 '21 at 12:40
  • Ok so the query is the problem I shouldn't query over anything ? –  May 02 '21 at 12:43
  • Yes. You should update a counter each time there is an addition or deletion to your collection and read this counter doc(s) when needed. See the doc for distributed counters. If my answer helped you please upvote it. Thank you. – Renaud Tarnec May 02 '21 at 12:44
  • But how can I get the docs then when I only updating the counter is there any example for counter ?? –  May 02 '21 at 12:55
  • ok f.. off I deside to saved also the uid of the user that uploads the video and now I wanna use that like you said f... that billing..How can I use now the collectiongroup –  May 02 '21 at 13:04
  • Using collectionGroup will result in the same situation => You will pay for all the videos docs that you read. The only recommended approach is to use counters. It is not difficult, the doc explains it very well. – Renaud Tarnec May 02 '21 at 13:08
  • Maybe for you but for me hundred precent not –  May 02 '21 at 13:10
  • if I opened a new question would you maybe help ? –  May 02 '21 at 13:12
  • Have a look at https://stackoverflow.com/questions/54808214/count-with-firestore-cloud-functions/54812624#54812624. If you have problem implementing this solution you may create a new question. – Renaud Tarnec May 02 '21 at 13:24
  • Hey ok maybe I found a solution in my case maybe you can check out this question https://stackoverflow.com/questions/67383104/class-listdynamic-has-no-instance-method-substring –  May 04 '21 at 10:35