From the https://firebase.google.com/docs/firestore/query-data/queries documentation snippet, Im unable to get the results as an Observable
import { collectionGroup, query, where, getDocs } from "firebase/firestore";
const museums = query(collectionGroup(db, 'landmarks'), where('type', '==', 'museum'));
const querySnapshot = await getDocs(museums);
querySnapshot.forEach((doc) => {
console.log(doc.id, ' => ', doc.data());
});
So I wrote it like this:
const museums = query(
collectionGroup(db, 'landmarks'),
where('type', '==', 'museum')
);
const querySnapshot = await getDocs(museums);
const datas = querySnapshot.docs.map((doc) => {
return doc.data() as Data;
});
console.log(datas);
return of(datas);
But I'm not getting results when subscribing to it or in the DOM using async pipe, but when I console.log(), there is an array of data.
component.html
{{ museums_data$ | async }}
component.ts
this.museums_data$.subscribe((datas) => console.log(datas));
CodePudding user response:
I found it here: https://code.build/p/LWmSi3HfQzu5TMKPzb5p6i/angular-12-with-firebase-9, which is written for the collection. Assuming it should also work for collection groups, I tried it, and it performed as expected.
This is a code snippet found in the link:
collectionData<Post>(
query<Post>(
collection(this.afs, 'posts') as CollectionReference<Post>,
where('published', '==', true)
), { idField: 'id' }
);
to:
collectionData<Landmark>(
query<Landmark>(
collectionGroup(db, 'landmarks') as CollectionReference<Landmark>,
where('type', '==', 'museum')
), { idField: 'id' }
);
CodePudding user response:
At First glance code looks good but you are returning it incorrectly. Instead of mapping over you can return it directly using as Observable<Data[]>
. Although I have not considered the error handling this can easily be achieved using the catchError
rxjs operator.
You can use the following technique to get the data as you want using an async
pipe.
data.service.ts :
import { Injectable } from '@angular/core';
import { collection, collectionData, Firestore, query, where
} from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { Data } from './data;
@Injectable({
providedIn: 'root',
})
export class DataService {
constructor(private db: Firestore) {}
getData(): Observable<Data[]> {
const ref = collection(this.db, 'landmarks);
const q = query(ref, where(type, '==', museum));
const data = collectionData(q, {
idField: 'id',
});
return data as Observable<Data[]>;
}
And use it like this in the corresponding component:
app.component.ts :
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { DataService } from './data.service';
import { Data } from './data;
@Component({
selector: 'app-root',
template: `
<div *ngFor="let museum of museums_data$ | async">
{{ museum.id }} // …
</div> `,
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
museums_data$!: Observable<Data[]>;
constructor(private service: DataService) {}
ngOnInit(): void {
this.museums_data$ = this.service.getData();
}
}
For more information there is this article that explains nicely.