在 Angularfire2 中“加入"Firebase 查询 [英] 'Joining' Firebase Queries in Angularfire2

查看:22
本文介绍了在 Angularfire2 中“加入"Firebase 查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:

我遇到的空值字段的问题与我的数据库中不存在的键有关,所以这里的大部分讨论都不适用于您的问题.如果您正在寻找一种在 AngularFire2 中加入"查询的方法,下面接受的答案可以很好地完成这项工作.我目前使用 combineLatest 而不是 forkJoin.为了做到这一点,你必须import 'rxjs/add/observable/combineLatest';.

我有以下非规范化的 Firebase 结构:

成员-memberid1-线程-threadid1:真,-threadid3:真-用户名:亚当"...线程-threadid1-作者:memberid3-质量:67-参与者-memberid2:真,-memberid3: 真...

我想在我的 threads 视图中呈现 username,该视图按 quality 排序.

我的服务:

getUsername(memberKey: string) {return this.af.database.object('/members/' + memberKey + '/username')}getFeaturedThreads(): FirebaseListObservable

我想将这些值放入 threads 的属性中,这样我就可以像这样在我的视图中呈现它:

...{{threads.username}}...

更新:console.log 用于allThreadsthisThread

更新:订阅了 getUsername()

this.featuredThreadsService.getUsername(thisThread.author).subscribe( 用户名 => console.log(用户名))

这样做的结果是没有值的对象:

解决方案

您可以基于 getFeaturedThreads 编写一个 observable,它查询成员并将每个线程的 participants 属性中的值替换为用户名:

import { Observable } from 'rxjs/Observable';导入 'rxjs/add/observable/forkJoin';导入 'rxjs/add/operator/do';导入 'rxjs/add/operator/first';导入 'rxjs/add/operator/switchMap';让 featuresThreadsWithUserNames = this.getFeaturedThreads()//每次 getFeaturedThreads 发出时,切换到取消订阅/忽略//任何待处理的成员查询:.switchMap(线程=> {//将线程映射到要被观察的数组//加入.当 observables 发出一个值时,更新线程.让 memberObservables = [];线程.forEach(线程=> {//添加作者:memberObservables.push(this.af.database.object(`成员/${thread.author}`).第一的().do(value => { thread.author = value.username; }));//添加参与者:Object.keys(thread.participants).forEach(key => {memberObservables.push(this.af.database.object(`成员/${key}`).第一的().do(value => { thread.participants[key] = value.username; }));});});//加入成员 observables 并使用结果选择器//返回线程 - 将被更新.return Observable.forkJoin(...memberObservables, () => 线程);});

这将为您提供每次 getFeaturedThreads 发出时发出的 observable.但是,如果用户名更改,则不会重新发出.如果这很重要,请将 forkJoin 替换为 combineLatest 并从组合成员可观察对象中删除 first 运算符.

Update:

The issues I was encountering with the empty value fields had to do with non-existent keys in my database, so most of the discourse here won't apply to your question. If you're looking for a way to 'join' queries in AngularFire2, the accepted answer below does a fine job of this. I'm currently using combineLatest instead of forkJoin. In order to do this you have to import 'rxjs/add/observable/combineLatest';.

I have the following denormalized Firebase structure:

members
  -memberid1
    -threads
       -threadid1: true,
       -threadid3: true
    -username: "Adam"
    ...

threads
  -threadid1
      -author: memberid3
      -quality: 67
      -participants
         -memberid2: true,
         -memberid3: true
     ...

I want to render username in my threads view, which is sorted by quality.

My service:

getUsername(memberKey: string) {
    return this.af.database.object('/members/' + memberKey + '/username')
}

getFeaturedThreads(): FirebaseListObservable<any[]> {
    return this.af.database.list('/threads', {
        query: {
            orderByChild: 'quality',
            endAt: 10
        }
    });
}

My component:

ngOnInit() {
    this.threads = this.featuredThreadsService.getFeaturedThreads()
    this.threads.subscribe( 
        allThreads => 
        allThreads.forEach(thisThread => {
            thisThread.username = this.featuredThreadsService.getUsername(thisThread.author)
            console.log(thisThread.username)
        })
    )
} 

For some reason this logs what looks like unfulfilled observables to the console.

I'd like to get these values into a property of threads so I can render it in my view like this:

<div *ngFor="let thread of threads | async" class="thread-tile">
    ...
    {{threads.username}}
    ...
</div>

Updated: console.log for allThreads and thisThread

Updated: subscribed to getUsername()

this.featuredThreadsService.getUsername(thisThread.author)
        .subscribe( username => console.log(username))

The result of this is objects with no values:

解决方案

You can compose an observable based on getFeaturedThreads that queries members and replaces the values in each thread's participants property with user names:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/switchMap';

let featuredThreadsWithUserNames = this.getFeaturedThreads()

  // Each time the getFeaturedThreads emits, switch to unsubscribe/ignore
  // any pending member queries:

  .switchMap(threads => {

    // Map the threads to the array of observables that are to be
    // joined. When the observables emit a value, update the thread.

    let memberObservables = [];
    threads.forEach(thread => {

      // Add the author:

      memberObservables.push(this.af.database
        .object(`members/${thread.author}`)
        .first()
        .do(value => { thread.author = value.username; })
      );

      // Add the participants:

      Object.keys(thread.participants).forEach(key => {
        memberObservables.push(this.af.database
          .object(`members/${key}`)
          .first()
          .do(value => { thread.participants[key] = value.username; })
        );
      });
    });

    // Join the member observables and use the result selector to
    // return the threads - which will have been updated.

    return Observable.forkJoin(...memberObservables, () => threads);
  });

This will give you an observable that emits each time getFeaturedThreads emits. However, if the user names change, it won't re-emit. If that's important, replace forkJoin with combineLatest and remove the first operator from the composed member observables.

这篇关于在 Angularfire2 中“加入"Firebase 查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆