【问题标题】:Storing object references in JSON在 JSON 中存储对象引用
【发布时间】:2013-12-31 11:14:42
【问题描述】:

我目前正在构建一个非常复杂的 AngularJS 应用程序,它将数据存储在 sqlite 数据库中。我的应用程序数据包含对整个应用程序共享的对象的引用。 Angular 能够渲染这些数据,进行比较,到目前为止一切都很好。

这一切是什么意思?查看此示例以了解我的应用程序中对象的“样板”。

var Person = {
    name:'some person',
    owns:[]
}

var Cat = {
    name:'some cat'
}

var project = {
    name:'some project',
    people:[],
    cats:[]
}

我的应用程序将允许用户创建和操作这些对象,并在它们之间创建关系。可以创建Person 的实例,并且每个Person 对象可以存储对Cat 实例的引用。

您可能已经猜到了,我的project 在用户完成操作后最终会是这个样子。

var project = {
    name:'some project',
    people:[person, person, person],
    cats:[cat, cat cat, cat, cat, cat]
}

console.log(project.people[0].owns)
//logs something like "cat, cat, cat". These are references.

然后我的应用程序设置了查看每个person 的视图,并将列出owns 属性,其中包含Cat 的实例。

一切都很好,直到我意识到将其作为 JSON 存储在数据库中可能会很复杂。 JSON.Stringify()angular.toJSON() 不将引用视为引用,而是将它们视为单独的对象。

我希望对保留这些关系/参考的最佳方式有所了解。

这是我认为我有的两个选项。

选项 1: 放弃将其存储在 JSON 中的想法,并使用关系数据库来存储所有内容。这并不理想,因为它开始侵蚀 AngularJS 中对象渲染的灵活性。此外,这些数据将存储在多个位置(在线和本地),这可能会导致数据库方案存在差异,这将是调试的噩梦。

选项 2:PersonCat 的每个实例存储一个唯一标识符。然后我可以在渲染和创建关联时使用这个标识符。如果我在 Angular 中创建自定义过滤器,这将起作用,但在删除对象时全局删除引用可能是一场噩梦。

【问题讨论】:

  • 我真的不知道这些 JSON DB 是如何存储它们的数据的,但是当您尝试序列化“Fred 拥有 Dino”和“Dino 由 Fred 拥有”时,您是否已经遇到了无限回归问题“?所以这甚至不是检索的问题,但似乎没有明确的方法来存储这些,除非数据库已经为你创建了引用......或者我错过了一些基本的东西?
  • 你说得对,斯科特,我编辑了我的问题以反映你的担忧。在我的应用程序(以及上面的示例中)中,这是一种单向关系。不需要“owned_by”,一开始我错过了。
  • 有了这个,我相信一些 JSON 存储引擎,如 Mongo 和 Couch 将存储足够的元数据,以便在检索您的 project 对象时重建这些关系。但我不知道sqllite。他们不会检索的是您可能用来创建这些对象的任何构造函数。如果你只使用普通的 JS 对象,这根本不会受到伤害。
  • 关于选项 2:你能解释一下吗? “如果我在 Angular 中创建自定义过滤器,这将起作用,但在删除对象时全局删除引用可能是一场噩梦。”
  • 我自己也在考虑类似的问题。我也倾向于使用一些本地(或全球?)唯一 ID 的每个实例,但出于其他原因。本质上是为了鼓励分离客户端存储对象的关注点,以及计算任何派生数据的 OO 类型方法。例如,可能有 Cat 和 Person 服务,它们公开了 Cat.getOwnedBy(personId) 和 PersonService.getAge(personId) 等方法。每个服务将尽可能只处理其“类”的数据。

标签: javascript json sqlite angularjs database-design


【解决方案1】:

传统的基于表的关系数据库已经解决了这个问题。可以在多个上下文中引用的每个记录/文档都存储在其自己的表/集合中,并带有idid 被它们自己集合中的其他对象引用。

JSON 本身只会保存原始数据,因此如您所见,发生变化的对象引用不是JSON 可以处理的。

那么问题就变成了,数据是一阶对象之间的关系吗?还是嵌套/嵌入到另一个对象中?

在你的例子中,一个项目有很多人,一个项目有很多猫,人们有很多项目。所以因为人和项目都需要被多个其他对象引用,每个资源都应该是它自己的资源,通过外键引用。

// projects.json
[
  {
    id: 4
    name: 'homework',
    person_ids: [1,2,3],
  }
]

// people.json
[
  {
    id: 1,
    name: 'Bob',
    project_ids: [4,5,6],
  }
]

一个很好的嵌入案例可能是项目中的 cmets。在这种情况下,您总是通过项目访问 cmets。而且因为评论只能属于一个项目,嵌入它更有意义。

// projects.json
[
  {
    id: 4
    name: 'homework',
    person_ids: [1,2,3],
    comments: [
      {
         person_id: 1,
         message: 'My dog ate it'
      ]
    ]
  }
]

我建议阅读Mongoid handles relations 的方法。它是 MongoDB 的 ruby​​ 包装器,但文档解释了它如何构造集合以启用关系。您可能会发现了解它的工作原理很有帮助。

【讨论】:

  • 嗨,Alex,这是一个很好的回应,并提供了我正在寻找的见解。我将把这个话题留得更久一些,因为我觉得这是一个很好的、发人深省的对话,可能会吸引更多的答案。
猜你喜欢
  • 2013-03-08
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2017-12-24
  • 2016-06-16
相关资源
最近更新 更多