【问题标题】:Observable object field as query parameter in firestore可观察对象字段作为 Firestore 中的查询参数
【发布时间】:2019-08-01 18:53:19
【问题描述】:

我有一个身份验证服务和一个角度查询服务。

Auth 服务负责登录并跟踪用户对象(可观察)

import {Injectable} from '@angular/core';
import {AngularFireAuth, AngularFireAuthModule} from '@angular/fire/auth';
import {AngularFirestore, AngularFirestoreModule} from '@angular/fire/firestore';
import {Observable, of} from 'rxjs';
import {User} from '../models/user';
import {switchMap} from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

    user: Observable<User>;

    constructor(private fireAuth: AngularFireAuth, private fireStore: AngularFirestore) {
        this.user = this.fireAuth.authState.pipe(
            switchMap(user => {
                if (user) {
                    return this.fireStore.doc<User>(`users/${user.uid}`).valueChanges();
                } else {
                    return of(null);
                }
            }));
    }
}

在我的查询服务中,我想根据登录的用户 ID 获取一些文档。这就是我在查询服务中添加 authService 作为构造函数参数的原因(可能不是最好的方法)。

查询文档的过程如下:

this.data = this
              .fireStore
              .collection<Blimp>(
                  'blimps',
                  ref => ref.where('userIdTo', '==', ??ID_FROM_OBSERVABLE??)
              )
              .valueChanges()
              .pipe(map(collection => {
                  return collection.map(b => {
                      let blimp = new Blimp();
                      blimp.fileLocation = b.fileLocation;

                      return blimp;
                  });
              }));

如您所见,我很难将 ID 输入该函数,因为我们正在使用 observable。

我的问题是,这里最好的方法是什么?

我正在尝试以下操作,但无法正常工作

this.blimps = this
              .fireStore
              .collection<Blimp>(
                  'blimps',
                  ref => ref.where('userIdTo', '==', this.authService.user.pipe(map((user) => user.userId)))
              )
              .valueChanges()
              .pipe(map(collection => {
                  return collection.map(b => {
                      let blimp = new Blimp();
                      blimp.fileLocation = b.fileLocation;

                      return blimp;
                  });
              }));

【问题讨论】:

    标签: angular firebase rxjs google-cloud-firestore


    【解决方案1】:

    您需要将您的用户 id 可观察的 switchMap 关闭:

    const userId$ = this.authService.user.pipe(map((user) => user.userId));
    
    this.blimps = userId$.pipe(
                    switchMap(userId => 
                      this
                        .fireStore
                        .collection<Blimp>(
                          'blimps',
                          ref => ref.where('userIdTo', '==', userId)
                        )
                        .valueChanges()
                        .pipe(map(collection => {
                          return collection.map(b => {
                            let blimp = new Blimp();
                            blimp.fileLocation = b.fileLocation;
                            return blimp;
                          });
                        })))
                    );
    

    这样,您在收到 userId 后切换到您的 firestore observable,您就可以将您的 userId 提供给您的 firestore observable。此外,您将在每次用户 ID 更改时自动取消并重新切换。

    【讨论】:

    • 由于某种原因,当我看其他示例时,我感觉switchMap不适合这个用例。也许你可以更详细地解释它在这个用例中是如何工作的,因为你的文字对我来说并不完全清楚。
    • switchMap 可能是您想要的。当一个新值来自源(在本例中为 userId)时,它将取消其先前的 firestore 订阅并切换到具有新使用 id 的新订阅。如果出于某种原因您想为一次通过的所有 userId 维护 firestore 订阅,请改用 mergeMap。但通常您一次只想订阅一个用户数据。
    猜你喜欢
    • 2022-06-12
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 2019-09-09
    • 2019-02-24
    • 1970-01-01
    • 2012-04-20
    • 2021-07-29
    相关资源
    最近更新 更多