Firebase data normalized. How should I fetch a collection based on this structure?

前端 未结 1 1184
予麋鹿
予麋鹿 2020-12-02 17:59

I think I am getting close, I am able to print out the ID of books belonging to a user but have been trying unsuccessfully to fetch the list of books belonging to a user, fr

相关标签:
1条回答
  • 2020-12-02 18:19

    Begin by updating to angularFire 0.6. This looks 0.3.*ish. angularFire has been changed to $firebase and has a much more powerful and simplified interface.

    Vanilla Firebase

    I'll do this the hard way first as I think there is great value in understanding the underlying principle here. It's fairly complex, and I'll only cover the essentials. There are a lot of tiny edge cases to be handled as well:

    angular.module('app', [])
        .controller('UsersController', function($scope, $firebase, $timeout, $routeParams){
          var userId = $routeParams.userId;
          $scope.user = $firebase(new Firebase('URL/user/'+userId));
    
          // or, for 3-way binding and automatic writes back to Firebase
          var userRef = $firebase(new Firebase('URL/users/'+userId)).$bind($scope. 'user');
    
          // grab this users' books using Firebase (the hard way)
          $scope.books = {};
          var booksRef = new Firebase('URL/books/');
    
          // fetch the user's book list dynamically because it may change in real-time
          var indexRef = new Firebase('URL/user/'+userId+'/books');
    
          // watch the index for add events
          indexRef.on('child_added', function(indexSnap) {
             // fetch the book and put it into our list
             var bookId = indexSnap.name();
             booksRef.child(bookId).on('value', function(bookSnap) {
                // trigger $digest/$apply so Angular syncs the DOM
                $timeout(function() {
                   if( snap.val() === null ) {
                      // the book was deleted
                      delete $scope.books[bookId];
                   }
                   else {
                      $scope.books[bookId] = snap.val();
                   }
                });
             });
          });
    
          // watch the index for remove events
          indexRef.on('child_removed', function(snap) {
             // trigger $digest/$apply so Angular updates the DOM
             $timeout(function(snap) {
                delete $scope.books[snap.name()];
             });
          });
    });
    

    Then the HTML (this will be the same for the other examples below):

    <div data-ng-repeat="(bookId, book) in books">
       {{bookId}}: {{book.title}}
    </div>
    

    Some of the edge cases not fully covered here:

    • data is not sorted by priority ordering
    • when a record is deleted from index, should call off() on data paths
    • changes in ordering of the index won't change order of data records
    • value of the index is not stored anywhere for reference (if it matters)

    FirebaseIndex

    FirebaseIndex is a simple utility that takes an index like your book list and manages the code we just created above in a bit more sophisticated manner.

    Unfortunately, FirebaseIndex doesn't support value events, so it can't be used with angularFire after 0.5.0 because of a change to angularFire's internal loading mechanisms. So it's not quite as short and sweet as it used to be.

    angular.module('app', [])
    .controller('UsersController', function($scope, $firebase, $timeout){
       var userId = $routeParams.userId;
       $scope.user = $firebase(new Firebase('URL/user/'+userId));
    
       var fb = new Firebase(URL);
       var index = new FirebaseIndex( fb.child('user/'+userId+'/books') );
       $scope.books = {};
    
       // almost magic
       index.on('child_added', function(snap) {
          $timeout(function() { $scope.books[snap.name()] = snap.val(); });
       });
    
       index.on('child_removed', function(snap) {
          $timeout(function() { delete $scope.books[snap.name()]; });
       });
    });
    

    Firebase.util.join

    Firebase-util is a much more powerful and sophisticated library for normalizing paths. Because it returns an object that works just like a regular Firebase reference, it can also be used seamlessly with angularFire 0.5 and above.

    angular.module('app', [])
    .controller('UsersController', function($scope, $firebase){
       var userId = $routeParams.userId;
       $scope.user = $firebase(new Firebase('URL/user/'+userId)); 
    
       var fb = new Firebase(URL);
       var ref = new Firebase.util.intersection( fb.child('user/'+userId+'/books'), fb.child('books') );
    
       // magic!
       $scope.books = $firebase(ref);
    });
    
    0 讨论(0)
提交回复
热议问题