我正在使用Firebase和angularfire(最新版本)。我的数据模型是:
main
所以基本上我需要在我的模板中显示所有用户的预订: {{reservations.service.name}} {{reservations.venue.name}}等。“主键”是用户ID。 我创建了助手,以获取单个文档:
VENUES {
[venue.id] {
name: string
}
}
SERVICES {
[document.id] {
venueid: string
name: string
price: number
}
}
USERS {
[user.id] {
name: string;
phone: number;
}
}
RESERVATIONS {
[document.id] {
uid: <--- userID from users
serviceid: <--- id of document from services collection
name: string;
}
}
因此当我需要获取一份文档时,它可以正常工作。要使用参考获取所有预订信息,
doc$(path: string): Observable<any> {
return this.afs
.doc(path)
.snapshotChanges()
.pipe(
map(doc => {
return { id: doc.payload.id, ...doc.payload.data() };
})
);
}
我从带有提供的uid的resevations集合中获取了所有文档。
几天前,我开始使用nosql。我对switchmap,map,combinatelatest()进行了一些研究,但我不知道如何使用它。
我的问题是:如何将所有可观察物合并为一个,以根据用户ID获得所有文档? 我需要从预订集合中获取文档,其中用户ID,用户数据和服务数据(基于Reservations.serviceid == services.document.id)
提前谢谢!
顺便说一句。
我尝试使用:
const $reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
但是它只允许我将管道与ref.where结合(我不知道serviceid直到获得预订)
答案 0 :(得分:1)
您可以为此使用Angularfire leftJoin(afs, joinKey, joinCollection, limit=100)
函数。
const reservations$ = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
const reservationsServices$ = reservations$.pipe(
leftJoin(afs, 'serviceid', 'services')
)
查看详细说明here。
答案 1 :(得分:0)
如果有人在寻找快速解决方案加入查询,我建议使用: https://github.com/AngularFirebase/133-firestore-joins-custom-rx-operators
在我的情况下,我使用leftJoinDocument。这是代码:
leftJoinDocument(field, collection) {
return source =>
defer(() => {
let collectionData;
const cache = new Map();
return source.pipe(
switchMap(data => {
cache.clear();
collectionData = data as any[];
const reads$ = [];
let i = 0;
for (const doc of collectionData) {
if (!doc[field] || cache.get(doc[field])) {
continue;
}
reads$.push(
this.afs
.collection(collection)
.doc(doc[field])
.valueChanges()
);
cache.set(doc[field], i);
i++;
}
return reads$.length ? combineLatest(reads$) : of([]);
}),
map(joins => {
return collectionData.map((v, i) => {
const joinIdx = cache.get(v[field]);
return { ...v, [field]: joins[joinIdx] || null };
});
}),
tap(final =>
console.log(
`Queried ${(final as any).length}, Joined ${cache.size} docs`
)
)
);
});
然后在我的页面模块中
getClientReservations() {
this.reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', 'MwdM8bak78eE1omf6u04KtqlE2X2'))
.valueChanges()
.pipe(
this.db.leftJoinDocument('uid', 'users'),
this.db.leftJoinDocument('serviceid', 'services'),
this.db.leftJoinDocument('venueid', 'venue')
);
}
感谢tobias为我提供提示:)