[英]Firebase Firestore: Query and get documents that contain the queried value in one of the fields
[英]Best way to get 4 documents with one query?
我正在使用 Firebase 和 angularfire(最新版本)。 我的數據模型是:
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;
}
}
所以基本上我需要在我的模板中顯示所有用戶預訂:{{reservations.service.name}} {{reservations.venue.name}} 等。“主鍵”是用戶 ID。 我創建了幫助程序,以獲取單個文檔:
doc$(path: string): Observable<any> {
return this.afs
.doc(path)
.snapshotChanges()
.pipe(
map(doc => {
return { id: doc.payload.id, ...doc.payload.data() };
})
);
}
所以當我需要一份文件時它可以工作。 要使用參考獲取所有預訂:
const $reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
我使用提供的 uid 從 resevations 集合中獲取所有文檔。
幾天前我開始使用 nosql。 我對 switchmap、map、combinelatest() 做了一些研究,但我不知道如何使用它。
我的問題是:如何將所有 observables 合並為一個獲取基於 userid 的所有文檔? 我需要從 reservations 集合中獲取文檔,其中包含 userid、用戶數據和服務數據(基於 reservations.serviceid == services.document.id)
先感謝您!
順便提一句。
我嘗試使用:
const $reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
const $services = this.afs.collection('services').valueChanges();
return combineLatest($reservations, $services).pipe(
map(([reservations, services]) => [...reservations, ...services])
)
但它只允許我將管道與 ref.where 結合起來(在我獲得預訂之前我不知道 serviceid)
您可以為此使用 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')
)
請在此處查看詳細說明。
如果有人正在尋找加入查詢的快速解決方案,我建議使用: 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')
);
}
謝謝托比亞斯給我提示:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.