【问题标题】:AngularFire2 - Pushing and deleting from an objects arrayAngularFire2 - 从对象数组中推送和删除
【发布时间】:2016-11-05 19:37:58
【问题描述】:

我有一个名为 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: ''

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

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

一个问题是如何在不替换整个列表的情况下更新此列表,因为其他用户也可能从中添加/删除。谢谢

【问题讨论】:

    标签: angular firebase firebase-realtime-database angularfire2


    【解决方案1】:

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

    您应该将回复器存储在它自己的根级节点中,而不是在帖子节点中嵌套“回复器”,如下所示:

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

    创建一个新服务来管理帖子回复者。然后将该服务注入您的 Posts 服务。加载帖子时,您可以使用此新服务来加载帖子回复者。以下是它的外观:

    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 中查询 post 和 repiers,然后返回一个新的 observale,等待这两个查询完成,然后将两者结合起来,并返回结果(设置了 .repliers 的 Post)。

    当您同时需要两个数据集时,这非常棒,但是等待第二个查询完成当然会影响性能。另一种方法是在返回之前简单地将回复者 FirebaseListObservable 保存在 Post 上。

    为什么要反规范化?

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

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

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

    /post-repliers/$postKey/3498j3u9fjd0329

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

    /post-repliers/$postKey/dzz09cu09j234f0

    将返回权限被拒绝错误。

    下一步是什么?

    我建议您阅读有关 firebase 非规范化 here 的内容,因为它将帮助您了解如何更好地构建数据库。

    还要查看 Firebase 安全规则文档here。拥有一个结构不良的数据库可能会使安全性变得非常困难,如果不是不可能的话。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      • 2016-11-26
      相关资源
      最近更新 更多