我试图了解如何使用JSON对象构建特定的数据集。
假设我有一堆用户并且我正在存储在我的数据库中(我正在使用firebase):
{
0--{name:"Dog", details:{somestuffhere}}
|
1--{name:"Cat", details:{somestuffhere}}
|
2--{name:"Cow", details:{somestuffhere}}
...
}
使用firebase我可以看看Dog使用的名称条目 / 0 /名称
我理解它的方式,当我调用firebase(我正在使用angularjs)时,它将传输整个JSON对象。这适用于较小的数据集,但假设数据集增加到甚至5MB。初始负载是非常慢的(在我看来),但事情可能不会太糟糕(虽然你只是挂在大量的数据上)。
我正在尝试构建一种构建数据的方法,所以如果我只想获取一个名单列表,那么我会根据名称(例如,如果用户点击)来提取详细信息。
理想情况下,我会调用/ name,它将仅返回所有名称(不是与之关联的其余数据)。
有人有任何建议吗?
编辑: 我使用Dog Cat Cow作为例子,实际上他们是人,应用程序可以添加名称和详细信息(在其他页面上)。我想首先看一个名字列表,然后点击它们作为链接,如果存在,如果名称不存在,我将创建它,然后允许添加“细节”。我希望这会有所帮助。 (我假设数据库总是会增长,这就是为什么我说5MB,实际上它可以增长到更多,但我不知道,这取决于使用情况)
答案 0 :(得分: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}}
}
}
现在,您可以使用普通的Firebase引用来加载/names
的所有子项,然后您可以决定要加载哪些详细信息。
添加新动物时,请务必添加相应的/names
条目。
你是正确的,AngularFire将加载给定路径的所有数据,但是我们可以使用我们的新数据结构来限制它。我们可以使用多个AngularFires并且更具选择性,而不是使用加载我们所有数据的单个通用AngularFire。
第一个AngularFire加载我们的名字列表。
// Load the list of names to $scope.names
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/names"), $scope, "names"));
然后,一旦用户选择动物,路径/names/{Animal}
的新AngularFire将用于动态加载该动物的细节。在此示例中,假设动物的唯一键存储在animalKey
变量
// Load the specific animal details to $scope.animal
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/animals/").child(animalKey), $scope, "animal"));
现在我们动物的数据暴露在$scope.animal
上,我们还没有加载关于其他动物的所有不需要的数据。
发表对此回答的评论
作为一般建议,永远不要使用递增的整数作为Firebase中的键。由于Firebase的实时性,两个用户将使用相同的递增整数键(在这种情况下,3
)添加新项目的可能性同时非常高,这将导致覆盖他们的一个条目。请改用Firebase的.push()
。
在您的方案中,您要做的是绕过AngularFire并在Firebase参考号上使用.push
。试试这个:
var newAnimalRef = (new Firebase('http://[Your Firebase].firebaseio.com'))
.child('animals')
.push({name: 'Fish', details: ""});
它将使用/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())
});
然后热潮,我们以干净,安全的方式增加了一个孩子。
以下是关于非规范化数据的link to an official blog post,如果您来自使用关系数据库,它通常是一个很好的资源。
在$scope
上可能创建与同一字段关联的多个AngularFires时要小心。如果您不小心,最终可能会对在Firebase中写入多个路径的单个字段进行更改。为了防止这种情况,要么只将AngularFire绑定到将定期拆除的$scope
(即特定于显示动物数据的模块的控制器),要么使用从AngularFire传递给已解决的承诺的解除关联方法作为I在my other answer中进行。