使用 RxJs 和 AngularFirestore 通过外键获取单个文档
Get a single document by foreign key in using RxJs and AngularFirestore
我编写了一个如下所示的查询:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments', ref => ref.where('bookingId', '==', id).limit(1))
.valueChanges()
.pipe(
flatMap(array => from(array)),
first()
);
}
其中 Payment
对象具有对 Booking
id 的唯一引用。我想查找给定 ID 的付款。
这似乎是纠正此查询的一种相当复杂的方法。
是否有更简单的方法来执行此操作 - 包括这里是否有代码味道使这变得困难?
您可以仅使用 Javascript 原生数组 API .find()
来完成,它会为您节省几行代码:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments')
.valueChanges()
.pipe(
map(allPayments=>allPayments.find(payment=>payment.bookingId === id))
);
}
或者您可以使用 .first()
运算符并提供其首次满足的条件:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments')
.valueChanges()
.pipe(
flatMap(array => from(array)),
first(eachPayment => eachPayment.bookingId === id)
);
}
请注意,过滤在幕后的工作方式存在根本差异。我个人更喜欢 Javascript 的原生函数,因为我觉得使用 from(array)
转换 observable 只是为了让它一个一个地发出数组序列有点多余。
另请注意,通过执行 ref => ref.where('bookingId', '==', id)
,您的过滤实际上发生在查询级别(也就是不在客户端)。如果你确信检索到的payments
个数不会很大,那么让客户端做过滤就好了;否则最好将处理部分卸载到服务器。
更简单一点的是:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments', ref => ref.where('bookingId', '==', id).limit(1))
.valueChanges()
.pipe(
map(array => array[0]),
);
}
如果未找到付款,这将返回 undefined
。
我编写了一个如下所示的查询:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments', ref => ref.where('bookingId', '==', id).limit(1))
.valueChanges()
.pipe(
flatMap(array => from(array)),
first()
);
}
其中 Payment
对象具有对 Booking
id 的唯一引用。我想查找给定 ID 的付款。
这似乎是纠正此查询的一种相当复杂的方法。
是否有更简单的方法来执行此操作 - 包括这里是否有代码味道使这变得困难?
您可以仅使用 Javascript 原生数组 API .find()
来完成,它会为您节省几行代码:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments')
.valueChanges()
.pipe(
map(allPayments=>allPayments.find(payment=>payment.bookingId === id))
);
}
或者您可以使用 .first()
运算符并提供其首次满足的条件:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments')
.valueChanges()
.pipe(
flatMap(array => from(array)),
first(eachPayment => eachPayment.bookingId === id)
);
}
请注意,过滤在幕后的工作方式存在根本差异。我个人更喜欢 Javascript 的原生函数,因为我觉得使用 from(array)
转换 observable 只是为了让它一个一个地发出数组序列有点多余。
另请注意,通过执行 ref => ref.where('bookingId', '==', id)
,您的过滤实际上发生在查询级别(也就是不在客户端)。如果你确信检索到的payments
个数不会很大,那么让客户端做过滤就好了;否则最好将处理部分卸载到服务器。
更简单一点的是:
getPaymentByBookingId(id: string): Observable<Payment> {
return this.afs.collection<Payment>('payments', ref => ref.where('bookingId', '==', id).limit(1))
.valueChanges()
.pipe(
map(array => array[0]),
);
}
如果未找到付款,这将返回 undefined
。