6

Assume that the data look like this

post: {
  authorId: '123AA',
  title: 'first Post',
  body: 'yay'
}

author: {
  uid: '123AA',
  displayName: 'Richard'
  email: 'im@richard.com'
}

I want to render a post with the author's name:

<div className="post">
  <div className="title">{post.title}</div>
  <div className="body">{post.body}</div>
  <div className="author-name">{post.author.displayName}</div> //problem
</div>

A fetched post item only contains an author's uid, but I need the author's displayName. How do I populate the author field when retrieving the posts? This is what I do to fetch the posts right now:

const postsRef = firebase.database().ref('posts/')
postsRef.on('value', (snapshot) => {
  this.setState({posts: snapshot.val()})
})
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Maximus S
  • 10,759
  • 19
  • 75
  • 154
  • 1
    Its better to remove reactjs from the tags, the question has nothing to do with React – webdeb Aug 05 '16 at 12:34
  • 1
    As far as I know you can't make "joins" with firebase, you need to make a second request to get something from another collection – Rafael Teles Aug 05 '16 at 12:57
  • 1
    so is that what people do? For every post that gets added, you make another request to get the user object from the server? – Maximus S Aug 05 '16 at 12:58
  • 1
    Check here a "join" example of firebase: https://www.firebase.com/docs/web/guide/structuring-data.html#section-join – Rafael Teles Aug 05 '16 at 13:05
  • 1
    @MaximusS a join indeed requires an extra call. These extra calls are not as expensive as most developers think, because [Firebase pipelines the requests over its existing connection](http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786). – Frank van Puffelen Aug 05 '16 at 14:25
  • @FrankvanPuffelen follow-up question: http://stackoverflow.com/questions/38807888/redux-firebase-data-sync – Maximus S Aug 06 '16 at 19:16

1 Answers1

8

Not sure in real firebase, but I use join quite often in angular2. Here my sample code.

import { Component, OnInit } from '@angular/core';
import { AngularFire } from 'angularfire2';
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map';

@Component({
  selector: 'app',
  templateUrl: `
    <ul>
        <li *ngFor="let p of posts | async">
            {{ p.title }} - {{ (p.authorName | async)?.displayName }}
        </li>        
    </ul>
`
})
export class InitComponent implements OnInit {
    posts: Observable<any[]>;

  constructor(private af: AngularFire) {}

  ngOnInit() {
      this.posts = this.af.database.list('/posts')
      .map(posts => {
          posts.map(p => {
              p.authorName = this.af.database.object('/authors/'+p.authorId);
          });
          return posts;
      });
  }

The database structure as follows:

/posts/postId/{authorId, title, body}
/authors/authorId/{displayName, email}

Hope this helps

codetinker
  • 754
  • 10
  • 9