gpt4 book ai didi

couchdb - CouchDB 文档建模原则

转载 作者:行者123 更新时间:2023-12-03 04:38:34 29 4
gpt4 key购买 nike

我有一个问题,我已经尝试回答一段时间了,但无法弄清楚:

您如何设计或划分 CouchDB 文档?

以博客文章为例。

半“关系”方法是创建一些对象:

  • 发帖
  • 用户
  • 评论
  • 标签
  • 片段

这很有道理。但我正在尝试使用 couchdb(出于所有原因,它很棒)来建模相同的事物,但这非常困难。

大多数博客文章都为您提供了如何执行此操作的简单示例。他们基本上以相同的方式划分它,但说你可以向每个文档添加“任意”属性,这绝对是好的。所以你在 CouchDB 中会有这样的东西:

  • 发布(在文档中使用标签和片段“伪”模型)
  • 评论
  • 用户

有些人甚至会说你可以把评论和用户放在那里,这样你就会有这样的:


<code>post {
id: 123412804910820
title: "My Post"
body: "Lots of Content"
html: "<p>Lots of Content</p>"
author: {
name: "Lance"
age: "23"
}
tags: ["sample", "post"]
comments {
comment {
id: 93930414809
body: "Interesting Post"
}
comment {
id: 19018301989
body: "I agree"
}
}
}</code>

这看起来非常好并且很容易理解。我还了解如何编写从所有帖子文档中提取评论的 View ,将它们放入评论模型中,与用户和标签相同。

但后来我想,“为什么不把我的整个网站放入一个文档中呢?”:


<code>site {
domain: "www.blog.com"
owner: "me"
pages {
page {
title: "Blog"
posts {
post {
id: 123412804910820
title: "My Post"
body: "Lots of Content"
html: "<p>Lots of Content</p>"
author: {
name: "Lance"
age: "23"
}
tags: ["sample", "post"]
comments {
comment {
id: 93930414809
body: "Interesting Post"
}
comment {
id: 19018301989
body: "I agree"
}
}
}
post {
id: 18091890192984
title: "Second Post"
...
}
}
}
}
}</code>

您可以轻松地创建 View 来找到您想要的内容。

那么我的问题是,如何确定何时将文档分成更小的文档,或者何时在文档之间建立“关系”?

我认为如果像这样划分的话,它会更加“面向对象”,并且更容易映射到值对象:


<code>posts {
post {
id: 123412804910820
title: "My Post"
body: "Lots of Content"
html: "<p>Lots of Content</p>"
author_id: "Lance1231"
tags: ["sample", "post"]
}
}
authors {
author {
id: "Lance1231"
name: "Lance"
age: "23"
}
}
comments {
comment {
id: "comment1"
body: "Interesting Post"
post_id: 123412804910820
}
comment {
id: "comment2"
body: "I agree"
post_id: 123412804910820
}
}</code>

...但随后它开始看起来更像关系数据库。很多时候,我继承的东西看起来像“文档中的整个站点”,因此用关系对其进行建模更加困难。

我读过很多关于如何/何时使用关系数据库与文档数据库的文章,所以这不是这里的主要问题。我更想知道,在 CouchDB 中建模数据时应用什么好的规则/原则。

另一个例子是 XML 文件/数据。一些 XML 数据的嵌套深度超过 10 层,我希望使用相同的客户端(例如 Ajax on Rails 或 Flex)来可视化,我将从 ActiveRecord、CouchRest 或任何其他对象关系映射器呈现 JSON。有时我会得到包含整个站点结构的巨大 XML 文件,如下所示,我需要将其映射到值对象以在我的 Rails 应用程序中使用,这样我就不必编写另一种序列化/反序列化数据的方法:


<code><pages>
<page>
<subPages>
<subPage>
<images>
<image>
<url/>
</image>
</images>
</subPage>
</subPages>
</page>
</pages></code>

所以一般的 CouchDB 问题是:

  1. 您使用什么规则/原则来划分文档(关系等)?
  2. 可以将整个网站放入一个文档中吗?
  3. 如果是这样,您如何处理具有任意深度级别的序列化/反序列化文档(如上面的大型 json 示例或 xml 示例)?
  4. 或者您不将它们转换为 VO,您只是决定“这些过于嵌套到对象关系映射中,所以我将使用原始 XML/JSON 方法访问它们”?

非常感谢您的帮助,如何使用 CouchDB 划分数据的问题让我很难说“从现在开始我应该这样做”。我希望尽快到达那里。

我研究了以下网站/项目。

  1. Hierarchical Data in CouchDB
  2. CouchDB Wiki
  3. Sofa - CouchDB App
  4. CouchDB The Definitive Guide
  5. PeepCode CouchDB Screencast
  6. CouchRest
  7. CouchDB README

...但他们还没有回答这个问题。

最佳答案

对此已经有一些很好的答案,但我想在选项组合中添加一些更新的 CouchDB 功能,以处理 viatropos 描述的原始情况。

拆分文档的关键点是可能存在冲突的地方(如前所述)。您永远不应该将大量“困惑”的文档保存在一个文档中,因为您将获得完全不相关的更新的单个修订路径(例如,添加注释以添加对整个站点文档的修订)。管理各种较小文档之间的关系或连接一开始可能会令人困惑,但 CouchDB 提供了多种选项来将不同的部分组合成单个响应。

第一个大问题是 View 整理。当您将键/值对发送到 Map/Reduce 查询的结果中时,键将根据 UTF-8 排序规则进行排序(“a”位于“b”之前)。您还可以将 Map/Reduce 中的复杂键输出为 JSON 数组:["a", "b", "c"]。这样做将允许您包含由数组键构建的排序“树”。使用上面的示例,我们可以输出 post_id,然后输出我们引用的事物的类型,然后输出其 ID(如果需要)。如果我们随后将引用文档的 id 输出到返回值中的对象中,我们可以使用“include_docs”查询参数将这些文档包含在 Map/Reduce 输出中:

{"rows":[
{"key":["123412804910820", "post"], "value":null},
{"key":["123412804910820", "author", "Lance1231"], "value":{"_id":"Lance1231"}},
{"key":["123412804910820", "comment", "comment1"], "value":{"_id":"comment1"}},
{"key":["123412804910820", "comment", "comment2"], "value":{"_id":"comment2"}}
]}

使用“?include_docs=true”请求相同的 View 将添加一个“doc”键,该键将使用“value”对象中引用的“_id”,或者如果“value”对象中不存在该“_id”,它将使用发出该行的文档的“_id”(在本例中为“post”文档)。请注意,这些结果将包含一个“id”字段,该字段引用发出的源文档。为了空间和可读性,我将其保留。

然后,我们可以使用“start_key”和“end_key”参数将结果过滤为单个帖子的数据:

?start_key=["123412804910820"]&end_key=["123412804910820", {}, {}]
或者甚至专门提取某种类型的列表:
?start_key=["123412804910820", "comment"]&end_key=["123412804910820", "comment", {}]
这些查询参数组合是可能的,因为空对象 (“ {}”) 始终位于排序规则的底部,而 null 或“”始终位于顶部。

在这些情况下,CouchDB 添加的第二个有用的功能是 _list 函数。这将允许您通过某种模板系统运行上述结果(如果您想要 HTML、XML、CSV 或其他任何形式),或者如果您希望能够请求整个帖子的内容(包括作者和评论数据)通过单个请求并作为与您的客户端/UI 代码所需的内容相匹配的单个 JSON 文档返回。这样做将允许您以这种方式请求帖子的统一输出文档:

/db/_design/app/_list/posts/unified??start_key=["123412804910820"]&end_key=["123412804910820", {}, {}]&include_docs=true
您的 _list 函数(在本例中名为“unified”)将获取 View 映射/reduce(在本例中名为“posts”)的结果,并通过 JavaScript 函数运行它们,该函数将以您的内容类型发回 HTTP 响应。需要(JSON、HTML 等)。

将这些内容结合起来,您可以在您认为对更新、冲突和复制有用且“安全”的任何级别拆分文档,然后在需要时根据需要将它们重新组合在一起。

希望有帮助。

关于couchdb - CouchDB 文档建模原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1530745/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com