Pregunta

Here's the scenario: I have a list of topics, each topic includes posts, and each post was "liked" by a list of users. Thus my data looks something like this:

"topics": {
    "topic1": {
        "posts": {
            "post1": true,
            "post2": true
        }
     }
 },
 "posts": {
     "post1": {
         "title": "An awesome post",
         "likes": {
             "user1": true
         }
     },
     "post2": {
         "title": "An even better post",
         "likes": {
             "user1": true,
             "user2": true
         }
     }
 },
 "users": {
     "user1": {
         "name": "Mr. T",
         "email": "t@t.com"
     },
     "user2": {
         "name": "Mr. Hello World",
         "email": "hello@world.com"
     }
 }

I (think I) know how to get all posts for the topic using Firebase.util (http://firebase.github.io/firebase-util):

Firebase.util.intersection(
    fb.child('topics').child('topic1').child('posts'),
    fb.child('posts')
)

But now I would like each post to include the names of the users who liked the post. How does one do that?

Probably won't change anything, but this is all happening in AngularFire.

¿Fue útil?

Solución

See a working example here

The gist of this sort of denormalization is to fetch the users as you grab posts. It's nothing more complex than it sounds. Just go grab them.

Firebase does a lot of work internally to optimize requests and re-uses the same socket connection for all the listeners, so this is quite performant--barely more overhead than the amount of bytes being downloaded, regardless of whether they are split into separate paths or stored together.

The HTML:

<h3>Normalizing user profiles into posts</h3>

<ul ng-controller="ctrl">
    <li ng-repeat="post in posts | orderByPriority" ng-init="user = users.$load(post.user)">
        {{user.name}}: {{post.title}}
    </li>
</ul>

The JavaScript:

var app = angular.module('app', ['firebase']);
var fb = new Firebase(URL);

app.controller('ctrl', function ($scope, $firebase, userCache) {
    $scope.posts = $firebase(fb.child('posts'));
    $scope.users = userCache(fb.child('users'));
});

app.factory('userCache', function ($firebase) {
    return function (ref) {
        var cachedUsers = {};
        cachedUsers.$load = function (id) {
            if( !cachedUsers.hasOwnProperty(id) ) {
                cachedUsers[id] = $firebase(ref.child(id));
            }
            return cachedUsers[id];
        };
        cachedUsers.$dispose = function () {
            angular.forEach(cachedUsers, function (user) {
                user.$off();
            });
        };
        return cachedUsers;
    }
});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top