JSON数据结构导致从数据库传递的数据最少

ona*_*000 1 json angularjs firebase angularfire

我试图了解如何使用JSON对象构建特定的数据集.

假设我有一堆用户,我就像这样存储在我的数据库中(我正在使用firebase):

 {
     0--{name:"Dog", details:{somestuffhere}}
     |
     1--{name:"Cat", details:{somestuffhere}}
     |
     2--{name:"Cow", details:{somestuffhere}}
    ...
 }
Run Code Online (Sandbox Code Playgroud)

使用firebase我可以使用/ 0/name查看Dog的名称条目

我理解它的方式,当我调用firebase(我正在使用angularjs)时,它将传输整个JSON对象.这适用于较小的数据集,但假设数据集增加到甚至5MB.初始负载是超慢的(在我看来),但事情可能不会太糟糕(虽然你只是挂在大量数据上玩).

我正在尝试构建一种构建数据的方法,所以如果我只想获取一个名单列表,那么我会根据名称(如果用户点击)来提取详细信息.

理想情况下,我会调用/ name,它将仅返回所有名称(不是与之关联的其余数据).

有没有人有什么建议?

编辑:我使用Dog Cat Cow作为例子,实际上他们是人,应用程序可以添加名称和详细信息(在其他页面上).我想首先看一个名字列表,然后点击它们作为链接,如果存在,如果名称不存在,我将创建它,然后允许添加"细节".我希望这会有所帮助.(我假设数据库将永远增长,这就是为什么我说5MB,实际上它可以增长到更多,但我不知道,这取决于使用情况)

Abe*_*ins 7

数据结构

使用Firebase构建时,对数据进行非规范化是关键.在您的场景中,我建议维护一个二级索引,该索引仅包含您的动物名称以及用于加载详细信息的唯一键.例如:

{
 "names": 
    {
      "Dog": 0,
      "Cat": 1,
      "Cow": 2
    },
 "animals": 
    {
       0: {name:"Dog", details:{somestuffhere}},
       1: {name:"Cat", details:{somestuffhere}},
       2: {name:"Cow", details:{somestuffhere}}
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用普通的Firebase引用来加载所有子项,/names然后您可以决定要加载哪些详细信息.

添加新动物时,只需确保添加相应的/names条目即可.

将此结构与AngularJS一起使用

你是正确的,AngularFire将加载给定路径的所有数据,但我们可以使用我们的新数据结构来限制它.我们可以使用多个AngularFires并且更具选择性,而不是使用加载我们所有数据的单个通用AngularFire.

第一个AngularFire加载我们的名字列表.

// Load the list of names to $scope.names
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/names"), $scope, "names"));
Run Code Online (Sandbox Code Playgroud)

然后,一旦用户选择动物,路径的新AngularFire将/names/{Animal}用于动态加载该动物的细节.在此示例中,假设动物的唯一键存储在animalKey变量中

// Load the specific animal details to $scope.animal
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/animals/").child(animalKey), $scope, "animal"));
Run Code Online (Sandbox Code Playgroud)

现在我们的动物数据暴露在外$scope.animal,我们还没有加载关于其他动物的所有不需要的数据.

安全地添加新动物

处理对此答案的评论

作为一般建议,永远不要使用递增的整数作为Firebase中的键.由于Firebase的实时性,两个用户将使用相同的递增整数键(在这种情况下3)添加新项目的可能性同时非常高,这将导致覆盖其中一个条目.请改用Firebase .push().

在您的场景中,您要做的是绕过AngularFire并.push在Firebase ref上使用.试试这个:

var newAnimalRef = (new Firebase('http://[Your Firebase].firebaseio.com'))
    .child('animals')
    .push({name: 'Fish', details: ""});
Run Code Online (Sandbox Code Playgroud)

它会创建一个/animals像孩子一样的新孩子-fj213jjkaisdja.然后我们可以使用.once将新项添加到/names索引:

newAnimalRef.once('value', function (snapshot) { 
    (new Firebase('http://[Your Firebase].firebaseio.com'))
        .child('names')
        .child(snapshot.val().name)
        .set(snapshot.name()) 
});
Run Code Online (Sandbox Code Playgroud)

然后繁荣,我们以干净,安全的方式增加了一个孩子.

结算笔记

  1. 以下是关于非正规化数据的官方博客文章的链接,如果您来自使用关系数据库,它通常是一个很好的资源.

  2. 在可能创建与同一字段关联的多个AngularFires时要小心$scope.如果您不小心,最终可能会对在Firebase中写入多个路径的单个字段进行更改.为了防止这种情况,要么只将AngularFire绑定到$scope将被定期拆除的(即显示动物数据的模块特定的控制器),要么使用与AngularFire中已解决的承诺相关的解除关联方法,就像我在其他答案中所做的那样.