Search code examples
angulargoogle-cloud-firestoreangularfire2

Angular Firestore (angularfire2) - Pull all "comments" that match a "photo" id


No idea how to properly "ask" this. I think in MySQL it was called "Joining" or something like that.

I have a collection called "Photos". I want the ability to add "Comments" to a photo. Those "Comments" will be stored in another collection. The structure for a comment his like this:

  • comment (string)
  • date (string - when was this posted)
  • photoId (the ID of the photo this comment belongs to).

I have an Angular page that already is displaying info about a Photo. Now I want to display the comments for that photo. How can I pull only the comments that belong to that photo??

Also, I want this to be asyc because I will have the ability to add a new comment "on the fly".

Thank you very much!


Solution

  • You can just query your comments collection like so:

    ...
    constructor(private afs: AngularFirestore) { 
        afs.collection('comments', ref => ref.where('photoId','==', this.idOfPhotoYouAreDisplaying)).valueChanges()
    }
    ...
    

    if you want to check for null in the template you can assign the result to a variable (eg comments):

    comments: Comment[];
    comments$: Observable<Comment[]>;
    
    constructor(private db: AngularFirestore) { 
    
        this.comments$ = this.db.collection(config.collection_comments, ref => ref.where('photoId', '==', this.photoId))
            .snapshotChanges()
            .pipe(
                map(actions => {
                    return actions.map(a => {
                        const data = a.payload.doc.data() as Comment;
                        const id = a.payload.doc.id;
                        return { id, ...data };
                    });
                }));
    }
    
    ngOnInit() {
        this.comments$.subscribe(c => this.comments == c);
    }
    

    Now in your template you can check on comments:

    <div *ngIf="comments">
        <div *ngFor="let comment of comments">
            ...
        </div>
    </div>
    

    Note 1: You don't have to assign it to a variable. You can check with the async pipe in ngIf, but when you loop over your comments, again with async you create a second subscription, which will cause you're query to execute twice.

    Note 2: Using the async pipe handles the unsubscription of your observable. When subscribing in the component you need to handle this yourself. (Multiple ways to do this)