angular - 从 id 与 rxjs Angular Firestore 合并可观察值

标签 angular firebase google-cloud-firestore rxjs angularfire

我有一个包含人和宠物的 Firestore 数据库,宠物有所有者 ID。

//集合/文档ID:{data}

persons / 'person1': { name: 'Romea' }
persons / 'person2': { name: 'Julieto' }
pets / 'pet1': { name: 'Forky', ownerID: 'person1' }
pets / 'pet2': { name: 'Rasky', ownerID: 'person1' }
pets / 'pet3': { name: 'Tursy', ownerID: 'person2' }

因此,当 Julieto 拥有 Tursky 时,Romea 拥有 Forky 和 ​​Rasky。

我正在使用@angular/fire,并且我想使用最新版本的 rxjs (6.5.x) 来获取用户与宠物的可观察值列表每个,参见以下结构:

[
   0: { 
         name: 'Romea',
         pets: [ 0: { name: 'Forky', ownerID: 'person1' }, 1: { name: 'Rasky', ownerID: 'person1' } ]
      },
   1: {
         name: 'Julieto',
         pets: [ 0: { name: 'Tursky', ownerID: 'person2' } ]
      }
]

毕竟,我想调用 person.pets,如下所示:

this.personService.getPersonsWithPets().subscribe(persons => {
   console.log(persons[0].pets)
   // result: [{ name: 'Forky', ownerID: 'person1' }, { name: 'Rasky', ownerID: 'person1' }]

   persons.forEach(person => person.pets.forEach(pet => console.log(pet.name)))
   // result: 'Forky', 'Rasky', 'Tursky'
})

解决方案

根据@bryan60的解决方案,这就是我所做的(rxjs加上一个在构造函数中接收人和宠物的类):

服务:

private personsCollection: AngularFirestoreCollection<Person> = this.db.collection<Person>('persons')

private _getPersonsWithoutPets(): Observable<Person[]> {
   return this.personsCollection.valueChanges()
}

getPersons(): Observable<(Person)[]> {
   return this._getPersonsWithoutPets().pipe(
      switchMap(persons => {
         return combineLatest(persons.map(person => this.getPersonPets(person.id).pipe(
            map(pets => new Person(person, pets))
         )))
      })
   )
}

getPersonPets(personId: string): Observable<Pet[]> {
   return this.db.collection<Pet>('pets', ref => ref.where('personId', '==', personId)).valueChanges()
}

型号:

export class Person {
   id?: string
   name: string

   public constructor(person: Person = null, private pets: Pet[] = null) {
       Object.assign(this, person)
       this.pets = pets
   }

   model?() {
      return {
         id: this.id,
         name: this.name
      }
   }
}

export class Pet {
   id?: string
   name: string

   constructor(pet: Pet = null) {
      Object.assign(this, pet)
   }

   model?() {
      return {
         id: this.id,
         name: this.name
      }
   }
}

组件:

personsWithPets: Person[] = []

constructor(private personService: PersonService) {
   this.getPersons()
}

getPersons() {
   this.personService.getPersons().subscribe(p => this.personsWithPets = p)
}

针对人员有多个引用对象(宠物、汽车)的情况的解决方案:

getPersonsWithReferences(): Observable<Person[]> {
  return this.getPersons().pipe(switchMap(persons =>
    combineLatest(persons.map(person =>
      combineLatest(this.getPersonPets(person.id), this.getPersonCars(person.id))
        .pipe(map(([pets, cars]) => new Environment(person, pets, cars)))))))
}

最佳答案

这是一个 switchMap 用例。

假设您有函数 getPersons()getPersonsPets(ownerID),它们执行其名称所暗示的操作,请执行以下操作:

getPersonsWithPets() {
  return this.getPersons().pipe(
    switchMap(persons => {
      return combineLatest(persons.map(person => this.getPersonsPets(person.id).pipe(
        map(pets => Object.assign(person, {pets}))
      )))
    })
  )
}

首先获取人员,switchMap 到将人员映射到他们的宠物流中的combineLatest,并将宠物分配给人员,然后返回人员及其宠物的列表。

有更多作业:

getPersonsWithPets() {
  return this.getPersons().pipe(
    switchMap(persons => {
      return combineLatest(persons.map(person => 
        combineLatest(
          this.getPersonsPets(person.id),
          this.getPersonsCars(person.id),
          this.getPersonsHouses(person.id)
        ).pipe(
          map(([pets, cars, houses]) => Object.assign(person, {pets, cars, houses}))
        )
      ))
    })
  )
}

关于angular - 从 id 与 rxjs Angular Firestore 合并可观察值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58961381/

相关文章:

asp.net - Angular 5 不会发回身份验证 cookie

javascript - Angular2/ typescript : How to get an array of objects through Pipe?

Angular 2 : Inserting capture element dynamically when creating components (dynamically)

javascript - 清除 Angular6 中表单的提交状态

javascript - 通过 Angular 在 firebase 中使用自定义标题而不是 ID 创建新项目

firebase - 有没有办法抑制 Firebase Functions Firestore 触发器?

firebase - 我们不能在事务内部查询集合吗?

android - 如何在不单击的情况下将通知标题或正文保存在后台

javascript - 如何使用 vue Js 将 firestore TIMESTAMPS 转换为完整日期

node.js - 如何获取 Firebase 中另一个集合的文档中的集合