【问题标题】:Firebase 3 - Many-to-many relationships...can't quite get itFirebase 3 - 多对多关系......不太明白
【发布时间】:2016-11-11 15:30:46
【问题描述】:

我对 Firebase 以及随之而来的新 Query API 还是比较陌生。

基本上,我有一个数据存储设置,用户可以在其中添加他们在个人资料中展示的 YouTube 视频。由于用户可以拥有很多视频,而视频可以拥有很多用户,因此我尝试根据最佳实践以适当的方式构建我的数据存储,如下所示:

{
    users {
     c25zdGFyb3NjaWFrQGdtYWlsLmNvbQ==
       videos {
         AFA-rOls8YA: true,
         AlLsp4gnyDQ: true,
         dX_1B0w7Hzc: true,
         ik5qR5bw75E: true,
         njos57IJf-0: true
       },
       videos {
         AFA-rOls8YA {
           attached_members {
             c25zdGFyb3NjaWFrQGdtYWlsLmNvbQ==: true
           }
           title: "Hello...it's me"
         },
         AlLsp4gnyDQ: { ... },
         dX_1B0w7Hzc: { ... },
         ik5qR5bw75E: { ... },
         njos57IJf-0: { ... },
         zn7-fVtT16k
        }
      }
    }
}

我可以做些什么来查询这些对象,以便我可以找回一个看起来像这样的用户:

c25zdGFyb3NjaWFrQGdtYWlsLmNvbQ: {
  videos: {
     AFA-rOls8YA: {
       attached_members: { ... }
       title: "Hello...it's me"
     },
     AlLsp4gnyDQ: { ... },
     dX_1B0w7Hzc: { ... },
     ik5qR5bw75E: { ... },
     njos57IJf-0: { ... },
     zn7-fVtT16k: { ... }
  }
}

我有很多情况需要发生这样的事情。我目前正在使用 Ionic 2、AngularFire 2,但如果需要,可以使用本机 Javascript SDK。我看到很多关于以这种方式构建数据的帖子,但我认为这些帖子不像回答如何使用 Firebase 3 以最优化的现代方式获取数据那样直截了当。

关于如何做到这一点的任何想法?

【问题讨论】:

  • 您是否有理由同时需要所有这些数据?
  • 是的,我将显示一个需要能够显示所有相关视频内容的个人资料页面

标签: angular firebase ionic2 angularfire2


【解决方案1】:

所以他们让你取消隔离的原因是能够绑定到端点而不加载大量数据。如果您在加载该节点时将所有数据都放在一个节点下,您将获得整个树。

我们会做您经常尝试做的事情,但这不是一个单一的查询调用。

我看到了 2 个主要选项,

一:对结果进行大循环的函数:

public getUser(userKey: string) {
  // assumes using af2
  return this.af.database.object('path/to/users/' + 'userKey').map((user) => {
    for ( let vidKey in user.videos) {
      if (user.videos.hasOwnProp(vidKey)) {
        this.af.database.object('path/to/vids/' + vidKey).map((video) => {
          user.videos[vidKey] = video;
        });
      }
    }
    return user;
  });
};

这会将您的用户作为对象加载,然后加载每个视频并在加载数据时更新对象。现在,如果您确实需要一个大对象,我只会使用此方法,但我认为您只想将其显示在用户列表中,然后在每个 vid 上显示详细信息:

选项 2:更小的函数

TS:

// before constructor
public user = this.getUser('1234');

//after constructor
public getUser(userKey: string) {
  return this.af.database.object('path/to/users/' + userKey);
}
public getUserVids(userKey: string) {
 return this.af.database.list('path/to/users/' + userKey + '/videos');
}
public getVideo(vidKey: string) {
  return this.af.database.object('path/to/vids/' + vidKey);
}

在模板中:

<div class="user" *ngIf="user">
    <h3>Name: {{user.name}}</h3>
    <div class="video" *ngFor="let video of geUserVids(user.$key) | async">
        <p>title: {{video.title}}</p>
        <p>length: {{video.length}}
    </div>
</div>

这种方式更小,功能可以在不同的地方使用。这使用了从 AF2 返回的 observables,但可能是你真正想要做的,而不是一个巨大的 json 对象......

【讨论】:

  • 非常感谢丹尼斯的简洁回答。事情是这样的,第一个选项实际上更符合我的需要,因为我正在为移动应用程序上的用户构建一个配置文件屏幕,所以没有那么多数据,但在我只需要一个对象的地方就足够了。我发现我创建了一个像你写的那样的函数,但是当我订阅它的结果时,它似乎没有命中嵌套的 for 循环对象调用来获取实际的视频。在这个例子中,订阅调用有什么奇怪的地方吗?或者你能给我一个我的组件可能是什么样子的例子吗?
  • 我认为您至少应该尝试两种调用方法,加载用户,然后加载 vids.. 但是要接听我的电话不使用订阅我正在映射,所以它返回结果的地图。如果你想要一个嵌套的 observable,你也可以尝试 flatMap()
猜你喜欢
  • 1970-01-01
  • 2018-03-19
  • 2017-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
  • 2017-11-11
  • 1970-01-01
相关资源
最近更新 更多