【问题标题】:Load comments in post在帖子中加载评论
【发布时间】:2015-12-04 20:49:48
【问题描述】:

假设我的 Firebase 数据库中有这个结构

编辑: 我的 JSON 结构如下所示:

{
  ad-comments:{
    48a047b7-28a2-4037-925c-2a809b8d4445:{
      -K4iGKXbniQZUi4r1SW7:{
         Comment:""
         Email:""
         Date:""
         Submitter:""
         ID:""
      }
      -K4hxcKuuxcwuhScPR_v:{...}    
    }
    eeb082e5-59ed-4c3b-8fcd-5af24a2bcada:{...}    
  }
  users:{
    48a047b7-28a2-4037-925c-2a809b8d4445:{
      text:""
      name:""
      email:""
      desc:""
      phone:""
    }
    444198db-1052-4d8d-a1cd-c7e613fbe7c9:{...}  
  }
}

在控制器中,我正在检索用户(每个用户都有一个属性帖子)以使用 $firebaseArray 和 ng-repeat 将它们显示在视图上,如下所示:

var ref = new Firebase ("https://url.firebaseio.com/users");
$scope.posts = $firebaseArray("ref");

现在在视图中,我只是使用 ng-repeat 来遍历它们

<div ng-repeat="post in posts">

  <div>{{post.name}}</div>
  <div>{{post.text}}</div>

  <div>Comments:<div>
     <div><input type="text" ng-model="comment"></div>
     <div><button ng-click="addComment(post, comment)">Add</button></div>
</div>

所以现在的问题是,当每个帖子位于不同节点时,我如何进行查询以请求每个帖子的所有 cmets,我按 ID 存储它们,但仍然不知道该怎么做。

在我将 cmets 存储在每个用户内部并且可以在每个帖子上显示 cmets 之前,但我遇到了安全规则问题,因为我已指定用户只能修改其自己的内容而不是其他人,而将 cmets 留在用户内部不允许其他人使用 cmets,所以我不得不更改并将 cmets 放在不同的节点中。

【问题讨论】:

  • 你能在代码中提供你的 JSON 数据结构吗?每个位置下只有几个样本应该会有所帮助。看起来你真的很亲密:)
  • @DavidEast 对不起,我不明白你的需要,你能解释一下吗?谢谢:)
  • 您上传了数据的图像,但它只提供了密钥。如果我看到了实际的 JSON 转储(只是一个示例,而不是全部),那就很容易回答了。
  • 啊好的,明白了,我编辑了我的问题希望是你需要的@DavidEast
  • post 的值是多少? ad-comments 和 posts 有什么区别?帖子是users 和`ad-cmets1 之间的数据连接吗?

标签: javascript angularjs firebase angularfire


【解决方案1】:

您的数据保持平稳,这太棒了!

您还在两个位置之间使用共享密钥,这意味着您已经完成了 90% 的路程。

有多种方法可以处理这种情况,但using .$extend() in AngularFire 提供了一个优雅的解决方案。

下面的代码示例使用Angular Styleguide,所以如果您对代码不熟悉,请不要担心。

Here's the full demo on JSBin,以下是创建它的步骤。

我们希望为每个用户加载 cmets。我们将首先创建一个通过uid 获取ad-comments 的工厂:

function UserCommentsArray($firebaseArray, rootRef) {
  return function UserCommentsArray(uid) {
    var userCommentsRef = rootRef.child('ad-comments').child(uid);
    return $firebaseArray(userCommentsRef);
  };
}

现在我们将使用$firebaseArray.$extend() 创建一个自定义同步数组。

function UsersArray($firebaseArray, rootRef, userCommentsArray) {
    return $firebaseArray.$extend({
      $$added: function(snap) {
        var user = snap.val();
        user.$id = snap.key();
        user.comments = userCommentsArray(snap.key());
        return user;
    }
  });
}

每次将一个项目添加到数组中时,我们都会创建一个用户对象并添加来自userCommentsArray 的 cmets。

现在在我们的控制器代码中,我们可以简单地注入 usersArray 并绑定到页面。

function MyCtrl($scope, rootRef, usersArray) {
  var usersRef = rootRef.child('users');
  $scope.users = usersArray(usersRef);
}

在页面上显示此数据需要更改模板:

  <div ng-controller="MyCtrl">

    <div ng-repeat="user in users">

      <div>{{user.name}}</div>

      <ul ng-repeat="comment in user.comments">
        <li>{{ comment.text }}</li>
      </ul>

      <div>Comments:</div>
      <div>
        <input type="text" ng-model="newComment">
      </div>

      <div>
        <button 
          ng-click="addComment(user, newComment)">Add
        </button>
      </div>

    </div>
  </div>

在用户下面添加 cmets 是通过找到用户然后在 cmets 数组上调用 $add() 来完成的。

function MyCtrl($scope, rootRef, usersArray) {
  var usersRef = rootRef.child('users');
  $scope.users = usersArray(usersRef);
  $scope.addComment = function (user, newComment) {
    var userRecord = $scope.users.$getRecord(user.$id);
    userRecord.comments.$add({ text: newComment });
  };
}

【讨论】:

  • 非常感谢,它成功了,终于我可以看到它工作了......耶!我欠你一些啤酒;)
  • 最后一个问题...我如何在遍历用户时添加 limitToFirst(n)?
  • 打开另一个问题。以这种格式回答会更容易。
【解决方案2】:

我不是 Firebase 专家,但我认为您应该考虑如何为帖子与其 cmets 之间的连接建模。 我可以想到两种方法:

  1. 帖子实体将有一个附加字段:

    列出commentIds

  2. 评论实体将持有帖子的 ID

我推荐第一种方法,因为通常我们希望所有者实体(在本例中为 Post 实体)保留其子实体(评论)

现在,当您检索 Post 时,请确保使用 cmets Id 检索其所有 cmets。

【讨论】:

  • Firebase 数据库是一个 NoSQL JSON 数据存储。没有本地连接或关系。有一种比加入 Firebase 更简单的技术。我想我知道问题出在哪里,但我需要查看数据的结构。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多