【问题标题】:JSON Data structure resulting in the least passed data from databaseJSON 数据结构导致从数据库中传递的数据最少
【发布时间】:2013-12-27 10:08:17
【问题描述】:

我试图了解如何使用 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,实际上它可以增长到更多但我不知道,这取决于使用情况)

【问题讨论】:

  • 这里的任何人都很难消化 Dog/Cat/Cowsomestuffhere 并将其转化为关于如何为他们一无所知的应用构建 5mb 数据交付的建议
  • 你想要的当然是一个真正的数据库。
  • 如果您希望数据库增长到 MB 范围内的某个位置,并希望您的用户可能不耐烦或不愿意等待数据同步以便于拥有所有数据并能够断开网络连接,那么您应该只使用常规数据库并传输您需要的数据。
  • 我还没有使用过firebase,但基于做了一些快速研究,它似乎依赖于客户端之间的数据同步,所以我想这意味着它第一次加载到设备中时会被缓存不知何故,然后变化可能是差异。
  • @Hot Licks - 假数据库有什么问题?还是您的意思是关系数据库?

标签: json angularjs firebase angularfire


【解决方案1】:

数据结构

使用 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 条目。

在 AngularJS 中使用这个结构

AngularFire 将加载给定路径的所有数据是正确的,但是我们可以使用我们的新数据结构来限制这一点。我们可以使用多个 AngularFire 并更具选择性,而不是使用单个通用 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 ref 上使用 .push。试试这个:

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

它将使用-fj213jjkaisdja 之类的键创建/animals 的新子级。然后我们可以使用.once 将新项目添加到/names 索引中:

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

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

结语

  1. 这是一个关于非规范化数据的link to an official blog post,如果您刚开始使用关系数据库,这通常是一个很好的资源。

  2. 在可能创建多个与$scope 上的同一字段关联的 AngularFire 时要小心。如果您不小心,最终可能会将单个字段的更改写入 Firebase 中的多个路径。为了防止这种情况,要么只将 AngularFire 绑定到将定期拆除的$scope(即特定于显示动物数据的模块的控制器),要么像我在my other answer.

【讨论】:

  • 响应#3,我如何将动物名称映射到提供的示例中的数字,同时保持实时性?很好的反应,当我整晚都在脑海中酝酿时,我得出了类似的结论。
  • 用更好的解释更新了我的答案。
猜你喜欢
  • 2016-01-05
  • 1970-01-01
  • 2011-05-18
  • 2014-03-24
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 2016-11-24
相关资源
最近更新 更多