首页 文章

Firebase数据已标准化 . 我该如何根据这个结构获取一个集合?

提问于
浏览
10

我想我已经接近了,我能够打印出属于用户的书籍的ID,但是从firebase书籍参考中一直尝试获取属于用户的书籍列表是不成功的 .

我在这里松散地阅读教程:http://www.thinkster.io/pick/eHPCs7s87O/angularjs-tutorial-learn-to-rapidly-build-real-time-web-apps-with-firebase#item-526e9330d90f99661f00046c

并阅读有关非规范化数据的文档:https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

如果我想在页面中显示用户,然后是所有书籍,我应该怎么做呢?

firebase结构

FB
|
--user
| |
| --user1
|   |
|   --name: "test name"
|   --email: "test@test.com"
|   --books
|     |
|     "-JFZG3coHOAblHZ7XSjK": true
|     "-KJKJASDIUOPIWE9WEeJ": true
|     "-YtUTRGJLNL876F3SSwS": true
|
--books
  |
  --"-JFZG3coHOAblHZ7XSjK"
  | |
  | --title: "book title 1"
  | --ownerId: "user1"
  |
  --"-KJKJASDIUOPIWE9WEeJ"
  |  |
  |  --title: "book title 2"
  |  --ownerId: "user1" 
  |    
  --"-YtUTRGJLNL876F3SSwS"
  |  |
  |  --title: "book title 2"
  |  --ownerId: "user1"

查看

<div data-ng-controller="UsersController" data-ng-init="findOneUser()">
  <h2>Profile</h2>
  <img class="image_preview" data-ng-src="{{user.photoUrl}}">
  <p>Name: {{ user.name }}</p>
  <p>Name: {{ user.email }}</p>
  <a data-ng-href="#/users/{{ userId }}/edit">Edit</a>

  <h2>Coffee Blends</h2>

  <div data-ng-repeat="book in user.books">
    <p>---</p>
    <p>{{user.books}}</p>
  </div>
  <!--<div data-ng-controller="BooksController" data-init="">-->

  <!--</div>-->
</div>

控制器

'use strict';

angular.module('ccApp.controllers.users', ['ccApp.services.users'])
    .controller('UsersController', ['$scope', '$routeParams', '$location', 'angularFire', 'Users',
      function($scope, $routeParams, $location, angularFire, Users){

      $scope.user = {};
      $scope.userId = $routeParams.userId;

      $scope.findOneUser = function(userId){
        if (!!$scope.userId){
          angularFire(Users.find($routeParams.userId), $scope, 'user');
        }
      };

      $scope.updatePhotoUrl = function(url, user){
        $scope.fileUrl = url;
        console.log($scope.fileUrl[0].url);
        user.photoUrl = $scope.fileUrl[0].url;
      };

      $scope.findUsers = function(){
        $scope.users = Users.collection();
      };

      $scope.findWholesalers = function(){
        $scope.wholesalers = Users.collection();
      };

    }]);

服务

'use strict';

angular.module('ccApp.services.users', ['ccApp.services.firebaseRefs'])
  .factory('Users', ['angularFireCollection', 'FireRef',
    function(angularFireCollection, FireRef){
      return{
        collection: function(cb){
          return angularFireCollection(FireRef.users(), cb);
        }
      , find: function(userId){
          return FireRef.users().child('/'+userId);
        }
      };
  }]);

1 回答

  • 16

    首先更新为angularFire 0.6 . 这看起来是0.3 . * ish . angularFire已更改为 $firebase ,并具有更强大和简化的界面 .

    Vanilla Firebase

    我将首先以艰难的方式做到这一点,因为我认为在这里理解基本原则是非常有 Value 的 . 它相当复杂,我只会介绍必需品 . 还有很多微小的边缘情况需要处理:

    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()];
             });
          });
    });
    

    然后是HTML(对于下面的其他示例,这将是相同的):

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

    这里没有完全覆盖一些边缘情况:

    • 数据未按优先级排序排序

    • 从索引中删除记录时,应在数据路径上调用off()

    • 索引排序的变化不会改变数据记录的顺序

    • 索引的值不存储在任何地方以供参考(如果重要的话)

    FirebaseIndex

    FirebaseIndex是一个简单的实用程序,它采用类似于您的图书列表的索引,并以更复杂的方式管理我们刚刚创建的代码 .

    不幸的是,FirebaseIndex不支持 value 事件,所以它可以't be used with angularFire after 0.5.0 because of a change to angularFire'的内部加载机制 . 所以它不像过去那么短暂和甜蜜 .

    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是一个功能更强大的复杂库,用于规范化路径 . 因为它返回一个像常规Firebase引用一样工作的对象,所以它也可以与angularFire 0.5及更高版本无缝地一起使用 .

    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);
    });
    

相关问题