AngularFire2 - 从对象数组中推送和删除

时间:2016-11-03 16:36:51

标签: angular firebase firebase-realtime-database angularfire2

我有一个名为Post的对象:

constructor(
    public repliers: string[''],
    public key: string = null
) {}

以下是推送帖子的服务方法:

submitPost(post: Post) {
    this.af.database.list('posts').push(post);
}

以下是订阅帖子表的方法:

subscribeAllPosts(): Observable<Post[]> {
    return this.af.database.list('posts')
    .map(Post.fromJsonList);
}

在post类中,这里是从json转换它的静态方法:

static fromJsonList(array:any): Post[] {
    return array.map(Post.fromJson);
}

static fromJson({repliers, $key }:any): Post {
    return new Post(repliers, $key );
}

当我提交帖子时,它起作用,而firebase上的帖子看起来像:

posts
    -> unique key
           ->  repliers
                     -> 0: ''

当我在提交一个帖子后循环浏览帖子时,我将数组视为具有一个默认空白键的属性。

我想解决的问题是如何更新posts表中的帖子,以便能够将额外的键推送到repliers数组并从数组中删除。

一个问题是如何更新此列表而不替换整个事物,因为其他用户也可能正在添加/删除它。感谢

1 个答案:

答案 0 :(得分:1)

解决此问题的正确方法是通过称为非规范化的过程稍微重构数据库。

不应在posts节点内嵌套“repliers”,而应将repisher存储在它自己的根级节点中,如下所示:

/posts/$postKey/{data1, data2, ...}
/post-repliers/$postKey/$replierKey/{data1, data2, ...}

创建新服务以管理帖子回复者。然后将该服务注入您的帖子服务。加载帖子时,您可以使用此新服务加载帖子回复者。以下是这可能的样子:

public getPost(postKey: string): Observable<Post>{
    let postSubscription = <Observable<Post>> this.angularFire.database.object(`/posts/${postKey}`)
      .map(this.mapPost);
    let postRepliersSubscription = <Observable<PostReplier[]>> this.postReplierService.getRepliersForPost(postKey);

    let postObservable = Observable.zip(postSubscription, postReplierSubscription).map((values) => {
      if(values[0])
        values[0].repliers = values[1];
      return values[0];
    });

    return postObservable;
  }

在这个解决方案中,我们查询firebase的帖子和repiers,然后返回一个新的observale,它将在梳理两个查询之前等待两个查询完成,并返回结果(Post设置.repliers)。 p>

当你同时需要两个数据集时,这很好,但是当然还有等待第二个查询完成的性能损失。另一种方法是在返回之前简单地将回复符号FirebaseListObservable保存在Post上。

为什么要归一化?

主要原因是安全性。 Firebase安全规则不允许您授予对一个属性的写入权限,并拒绝另一个属性。授予写访问权限时,可以为整个节点及其所有子节点执行此操作。

为了解决这个问题,我们将一个ownerKey添加到Post对象,并且只允许其UID与ownerKey匹配的用户修改Post对象。然后,通过将replierKey保存在post-repliers对象的路径中,我们允许任何人回复帖子,但是用户只能管理他们自己的post-replier对象。

例如,假设我的UID是3498j3u9fjd0329,我可以在以下位置创建一个回复:

/post-repliers/$postKey/3498j3u9fjd0329

但尝试删除其他用户的回复:

/post-repliers/$postKey/dzz09cu09j234f0

会返回权限被拒绝错误。

下一步是什么?

我建议您阅读firebase denormalization here,因为它可以帮助您了解如何更好地构建数据库。

另请参阅firebase安全规则文档here。拥有结构不良的数据库可能会使安全性变得非常困难,如果不是不可能的话。

祝你好运!