Query Firestore documents with role based security via Flutter












0















I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access



Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.



This is my data model (one sample document):



id: "1234-5678-91234",
roles:
userId_1:"owner",
userId_2:"editor
title: "This is a sample document"


And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:



return firestore
.collection(path)
.where("roles.${user.firebaseUserId}", isEqualTo: "owner")
.snapshots().map((snapshot) {
return snapshot.documents.map((catalog) {
return SomeDocumentObject(...);
}).toList();
});


My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".



I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).



I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.



Maybe someone of you have a hint for me? :)



Thanks & best,
Michael










share|improve this question





























    0















    I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access



    Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.



    This is my data model (one sample document):



    id: "1234-5678-91234",
    roles:
    userId_1:"owner",
    userId_2:"editor
    title: "This is a sample document"


    And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:



    return firestore
    .collection(path)
    .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
    .snapshots().map((snapshot) {
    return snapshot.documents.map((catalog) {
    return SomeDocumentObject(...);
    }).toList();
    });


    My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".



    I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).



    I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.



    Maybe someone of you have a hint for me? :)



    Thanks & best,
    Michael










    share|improve this question



























      0












      0








      0








      I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access



      Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.



      This is my data model (one sample document):



      id: "1234-5678-91234",
      roles:
      userId_1:"owner",
      userId_2:"editor
      title: "This is a sample document"


      And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:



      return firestore
      .collection(path)
      .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
      .snapshots().map((snapshot) {
      return snapshot.documents.map((catalog) {
      return SomeDocumentObject(...);
      }).toList();
      });


      My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".



      I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).



      I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.



      Maybe someone of you have a hint for me? :)



      Thanks & best,
      Michael










      share|improve this question
















      I´ve a role based data model on Firestore according to googles suggestion here: https://firebase.google.com/docs/firestore/solutions/role-based-access



      Security rules are set up correctly and work fine. But now I´ve the problem on how to query for the roles.



      This is my data model (one sample document):



      id: "1234-5678-91234",
      roles:
      userId_1:"owner",
      userId_2:"editor
      title: "This is a sample document"


      And this is my Firestore Query in Flutter which gets all documents for a specific user by its ID if the user has assigned the role "owner" for the document:



      return firestore
      .collection(path)
      .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
      .snapshots().map((snapshot) {
      return snapshot.documents.map((catalog) {
      return SomeDocumentObject(...);
      }).toList();
      });


      My problem now is, that I need some kind of "OR" clause - which does not exist as far as I know. The query above only retrieves documents for users with role "owner" but I need a query that also retrieves the document if the userId is associated with the role "editor".



      I´ve tried "arrayContains:" which also doesn´t seem to work (cause it´s a map).



      I´ve read about solutions with two independent queries which doesn´t sound like a good solution due to a lot of overhead.



      Maybe someone of you have a hint for me? :)



      Thanks & best,
      Michael







      flutter google-cloud-firestore






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 31 '18 at 14:52







      Michael

















      asked Dec 31 '18 at 14:46









      MichaelMichael

      699920




      699920
























          2 Answers
          2






          active

          oldest

          votes


















          1














          Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.






          share|improve this answer
























          • Thanks, that was what I expected - too sad :)

            – Michael
            Jan 1 at 12:57



















          0














          This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:



          @override
          Stream<List<Catalog>> catalogs(User user) {

          // Retrieve all catalogs where user is owner
          Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
          .collection(path)
          .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
          .snapshots());

          // Retrieve all catalogs where user is editor
          Observable<QuerySnapshot> editorCatalogs = Observable(firestore
          .collection(path)
          .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
          .snapshots());

          // Convert merged stream to list of catalogs
          return Observable.combineLatest([ownerCatalogs, editorCatalogs],
          (List<QuerySnapshot> snapshotList) {
          List<Catalog> catalogs = ;

          snapshotList.forEach((snapshot) {
          snapshot.documents.forEach((DocumentSnapshot catalog) {
          catalogs.add(Catalog(
          id: catalog.documentID,
          title: catalog.data['title'],
          roles: catalog.data['roles'],
          ));
          });
          });
          return catalogs;
          }).asBroadcastStream();
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53988693%2fquery-firestore-documents-with-role-based-security-via-flutter%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.






            share|improve this answer
























            • Thanks, that was what I expected - too sad :)

              – Michael
              Jan 1 at 12:57
















            1














            Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.






            share|improve this answer
























            • Thanks, that was what I expected - too sad :)

              – Michael
              Jan 1 at 12:57














            1












            1








            1







            Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.






            share|improve this answer













            Firestore doesn't currently have any logical OR operations. You'll have to perform two queries, one for each condition, and merge the results of both queries in the client app.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 31 '18 at 18:04









            Doug StevensonDoug Stevenson

            76.4k990111




            76.4k990111













            • Thanks, that was what I expected - too sad :)

              – Michael
              Jan 1 at 12:57



















            • Thanks, that was what I expected - too sad :)

              – Michael
              Jan 1 at 12:57

















            Thanks, that was what I expected - too sad :)

            – Michael
            Jan 1 at 12:57





            Thanks, that was what I expected - too sad :)

            – Michael
            Jan 1 at 12:57













            0














            This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:



            @override
            Stream<List<Catalog>> catalogs(User user) {

            // Retrieve all catalogs where user is owner
            Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
            .collection(path)
            .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
            .snapshots());

            // Retrieve all catalogs where user is editor
            Observable<QuerySnapshot> editorCatalogs = Observable(firestore
            .collection(path)
            .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
            .snapshots());

            // Convert merged stream to list of catalogs
            return Observable.combineLatest([ownerCatalogs, editorCatalogs],
            (List<QuerySnapshot> snapshotList) {
            List<Catalog> catalogs = ;

            snapshotList.forEach((snapshot) {
            snapshot.documents.forEach((DocumentSnapshot catalog) {
            catalogs.add(Catalog(
            id: catalog.documentID,
            title: catalog.data['title'],
            roles: catalog.data['roles'],
            ));
            });
            });
            return catalogs;
            }).asBroadcastStream();
            }





            share|improve this answer




























              0














              This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:



              @override
              Stream<List<Catalog>> catalogs(User user) {

              // Retrieve all catalogs where user is owner
              Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
              .collection(path)
              .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
              .snapshots());

              // Retrieve all catalogs where user is editor
              Observable<QuerySnapshot> editorCatalogs = Observable(firestore
              .collection(path)
              .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
              .snapshots());

              // Convert merged stream to list of catalogs
              return Observable.combineLatest([ownerCatalogs, editorCatalogs],
              (List<QuerySnapshot> snapshotList) {
              List<Catalog> catalogs = ;

              snapshotList.forEach((snapshot) {
              snapshot.documents.forEach((DocumentSnapshot catalog) {
              catalogs.add(Catalog(
              id: catalog.documentID,
              title: catalog.data['title'],
              roles: catalog.data['roles'],
              ));
              });
              });
              return catalogs;
              }).asBroadcastStream();
              }





              share|improve this answer


























                0












                0








                0







                This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:



                @override
                Stream<List<Catalog>> catalogs(User user) {

                // Retrieve all catalogs where user is owner
                Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
                .collection(path)
                .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
                .snapshots());

                // Retrieve all catalogs where user is editor
                Observable<QuerySnapshot> editorCatalogs = Observable(firestore
                .collection(path)
                .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
                .snapshots());

                // Convert merged stream to list of catalogs
                return Observable.combineLatest([ownerCatalogs, editorCatalogs],
                (List<QuerySnapshot> snapshotList) {
                List<Catalog> catalogs = ;

                snapshotList.forEach((snapshot) {
                snapshot.documents.forEach((DocumentSnapshot catalog) {
                catalogs.add(Catalog(
                id: catalog.documentID,
                title: catalog.data['title'],
                roles: catalog.data['roles'],
                ));
                });
                });
                return catalogs;
                }).asBroadcastStream();
                }





                share|improve this answer













                This is the final solution using RxDart, Observables and .combineLatest() - maybe it helps someone out there:



                @override
                Stream<List<Catalog>> catalogs(User user) {

                // Retrieve all catalogs where user is owner
                Observable<QuerySnapshot> ownerCatalogs = Observable(firestore
                .collection(path)
                .where("roles.${user.firebaseUserId}", isEqualTo: "owner")
                .snapshots());

                // Retrieve all catalogs where user is editor
                Observable<QuerySnapshot> editorCatalogs = Observable(firestore
                .collection(path)
                .where("roles.${user.firebaseUserId}", isEqualTo: "editor")
                .snapshots());

                // Convert merged stream to list of catalogs
                return Observable.combineLatest([ownerCatalogs, editorCatalogs],
                (List<QuerySnapshot> snapshotList) {
                List<Catalog> catalogs = ;

                snapshotList.forEach((snapshot) {
                snapshot.documents.forEach((DocumentSnapshot catalog) {
                catalogs.add(Catalog(
                id: catalog.documentID,
                title: catalog.data['title'],
                roles: catalog.data['roles'],
                ));
                });
                });
                return catalogs;
                }).asBroadcastStream();
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 1 at 21:27









                MichaelMichael

                699920




                699920






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53988693%2fquery-firestore-documents-with-role-based-security-via-flutter%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Mossoró

                    Error while reading .h5 file using the rhdf5 package in R

                    Pushsharp Apns notification error: 'InvalidToken'