使用RxJ和AngularFirestore通过外键获取单个文档

时间:2018-08-14 05:50:46

标签: rxjs angularfire2

我编写了一个查询,如下所示:

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的付款。

这似乎是解决该查询的一种复杂方法。

是否有更简单的方法来执行此操作-包括是否存在使此操作困难的代码气味?

2 个答案:

答案 0 :(得分:0)

您可以仅使用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)转换可观察对象只是一种多余的操作,以至于它可以逐一发出数组序列。

还要注意,通过执行ref => ref.where('bookingId', '==', id),过滤实际上发生在查询级别(即不在客户端)。如果您确信检索到的payments的数量不会很大,那么可以让客户端进行过滤;否则将处理部分卸载到服务器总是更好。

答案 1 :(得分:0)

简单一点:

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