在 AngularFirestore 中使用来自两个不同集合的数据构建对象时遇到问题

Posted

技术标签:

【中文标题】在 AngularFirestore 中使用来自两个不同集合的数据构建对象时遇到问题【英文标题】:Having trouble building an object with data from two different collections in AngularFirestore 【发布时间】:2020-06-28 21:20:58 【问题描述】:

我在 Firestore 中有一个植物集合(其中每个文档代表一种植物,并且每个植物都有自己的属性,例如 植物 ID、名称、描述、照片 URL...) 和包含用户的集合(其中每个文档代表具有自己属性的用户,包括具有他拥有的植物的植物 ID 的对象数组)

我想要实现的是,对于给定的用户,提供他拥有的植物的额外详细信息(不仅仅是 ID),这些详细信息在 Plants 集合中,所以我必须执行某种内连接操作使用用户文档中的植物 ID(检查 UserPlantView 接口声明以获得所需的输出;属性 imagedescription 将从 Plants 集合中获得)

我读到使用 rxjs 库中的 combineLatest 和 switchMap 可以做到这一点,但我无法完成它。我目前拥有的是:

plant-list.page.ts:

import 'firebase/firestore';
import  AngularFirestore  from '@angular/fire/firestore';
import  AngularFireAuth  from '@angular/fire/auth';
import  combineLatest, Observable  from 'rxjs'; 
import  switchMap  from 'rxjs/operators';

export interface Plant 
  name: string,
  pid: string,
  image: string,
  advices?: string,
  care?: string,
  clime?: string,
  curiosities?: string,
  depth?: string,
  description?: string,
  difficulty?: string,
  disease?: string,
  germinate?: string,
  irrigation?: string,
  location?: string,
  plant?: string,
  reap?: string,
  scientific?: string,
  season?: string,
  temperature?: string,
  transplant?: string,
  use?: string


export interface User 
  uid: string,
  name: string,
  email: string,
  plants?: [
    id: string,
    plant_name: string,
    custom_name: string
  ]


export interface UserPlantView 
  uid: string,
  name: string,
  plants?: [
    id: string,
    plant_name: string,
    custom_name: string,
    image: string,
    description: string
  ]


@Component(
  selector: 'app-plant-list',
  templateUrl: 'plant-list.page.html',
  styleUrls: ['plant-list.page.scss']
)
export class PlantListPage implements OnChanges 

  plantsNames: any;
  plantsList = [];
  prueba : UserPlantView;

  constructor(private AFauth: AngularFireAuth, private firestore: AngularFirestore) 
    this.getUsersPlantList();
  

  ngOnChanges() 
    this.getUsersPlantList();
  

  getUsersPlantList() 

    const plants : Observable<Plant[]> = this.firestore.collection<Plant>('plantas').valueChanges();
    const user : Observable<User> = this.firestore.collection('users').doc<User>(this.AFauth.auth.currentUser.uid).valueChanges();

    combineLatest(plants,user).pipe(
      switchMap(results => 
        const [plantsRes, userRes] = results;
        console.log(plantsRes);
        console.log(userRes);

        // Now I want to form a UserPlantView object using both the user document and the Plants collection...
        // ...

        return results;
      )
    ).subscribe(data => console.log(data));

  


这里有控制台日志的屏幕截图,信息已从 Firestore 正确检索,但我不知道如何继续。任何帮助将不胜感激!

【问题讨论】:

看起来你根本不需要使用switchMap。或者,如果你这样做了,你可以使用of() 将结果包装到一个 observable 中。 【参考方案1】:

在没有 switchMap 的情况下,我终于得到了我需要的工作。代码:

在 plant-list.page.ts 中:

getPlantsList() 

    const plants : Observable<Plant[]> = this.firestore.collection<Plant>('plantas').valueChanges();
    const user : Observable<User> = this.firestore.collection('users').doc<User>(this.AFauth.auth.currentUser.uid).valueChanges();

    combineLatest(plants,user).subscribe(data => 

      this.plantUserList =  as UserPlantView;
      this.plantUserList.uid = (<User>data[1]).uid;
      this.plantUserList.name = (<User>data[1]).name;
      if((<User>data[1]).plants) 
        this.plantUserList.plants = new Array();
        (<User>data[1]).plants.forEach(element => 
          this.plantUserList.plants.push(
              id : element.id,
              plant_name : element.plant_name,
              custom_name : element.custom_name,
              image : data[0].find(x=>x.pid == element.id).image,
              scientific: data[0].find(x=>x.pid == element.id).scientific
            )
        );
      
    );

  

在 plant-list.page.html:

<ng-container *ngIf="plantUserList">
<ion-item *ngFor="let item of plantUserList.plants">

  <ion-card ion-button routerLink="/tabs/tab1/item.id">
    <img  [src]="item.image">
    <ion-card-header>
      <ion-card-subtitle>20/02/2019</ion-card-subtitle>
      <ion-card-title>item.custom_name</ion-card-title>
    </ion-card-header>

    <ion-card-content>
      <b>item.plant_name</b> (item.scientific)
    </ion-card-content>
  </ion-card>
</ion-item>
</ng-container>

【讨论】:

以上是关于在 AngularFirestore 中使用来自两个不同集合的数据构建对象时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 AngularFirestore 和 firebase 的“ERROR TypeError: Object(...) is not a function”

无法解析 AngularFirestore 的所有参数:([object Object], ?)

Angular Firestore 查询中的 get() 和 valueChanges() 有啥区别? [关闭]

Makefile:来自相同源的两个目标使用不同的标志编译两次

使用 Firebase 订购 [关闭]

如何使用mapreduce实现两表join