Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Couchbase的数据迁移文档(即更改现有字段类型)?_Couchbase_Nosql - Fatal编程技术网

Couchbase的数据迁移文档(即更改现有字段类型)?

Couchbase的数据迁移文档(即更改现有字段类型)?,couchbase,nosql,Couchbase,Nosql,我来自对象关系数据库的背景,我知道Couchbase没有模式,但随着应用程序的发展,数据迁移仍然会发生 在SQL中,我们有管理工具来更改表,或者我可以用SQL编写迁移脚本,从版本1表迁移到版本2表 但在文档中,假设我们有json文档UserProfile: UserProfile { "Owner": "Rich guy!", "Car": "Cool car" } 我们可能希望在此处添加“上次访问”字段,允许用户拥有多辆车,因此新更新的文档将如下所示: UserProfile {

我来自对象关系数据库的背景,我知道Couchbase没有模式,但随着应用程序的发展,数据迁移仍然会发生

在SQL中,我们有管理工具来更改表,或者我可以用SQL编写迁移脚本,从版本1表迁移到版本2表

但在文档中,假设我们有json文档UserProfile:

UserProfile
{
  "Owner": "Rich guy!",
  "Car": "Cool car"
}
我们可能希望在此处添加“上次访问”字段,允许用户拥有多辆车,因此新更新的文档将如下所示:

UserProfile
{
  "Owner": "Rich guy!",
  "Car": ["Cool car", "Another car"],
  "LastVisit": "2015-09-29"
}
但为了便于维护,我希望所有其他UserProfile文档都采用相同的格式,以“Car”字段作为数组

根据我在SQL方面的经验,我可以编写支持迁移不同版本表的迁移脚本。从版本1表迁移到版本2…N表

那么,我应该如何编写这样的迁移代码呢?我真的需要使用Couchbase SDK编写一个应用程序(可执行文件)来迁移所有文档吗


像这样进行迁移的好方法是什么?

如果我理解正确,这里的关键是获取然后“更新每个CB文档”。这可以通过一个视图来完成,前提是您理解视图只是“最终一致的”(不同于读/写操作,读/写操作是高度一致的)

如果(在迁移时)没有新文档添加到bucket中,那么视图将是最新的,并且应该返回要迁移的整个文档集。简单

另一方面,如果新文档继续写入到您的bucket中,并且这些文档需要迁移,那么您必须持续运行迁移代码以捕获所有这些新文档(因为视图在几秒钟后更新后才会返回它们)

在第二个场景中,当迁移发生时,您的bucket将包含一个异构的文档集合:一些已经迁移,一些即将迁移,还有一些视图尚未“看到”(因为它们是最近添加的),并且只有在重新运行迁移代码后才会迁移

为了使迁移过程高效,您需要找到一种方法来区分已经迁移的项目和尚未迁移的项目。您可以在每个文档中添加一个带有“版本号”的字段,并在迁移过程中进行更新。您的视图应定义为仅选择具有较旧“版本号”的文档,并忽略已迁移的项目

我建议你在这里和他们的网站上阅读更多关于couchbase视图的信息

关于迁移:这里有两个方面:(1)获取需要更新的文档ID列表;(2)实际更新

实际更新很简单:检索文档并使用新格式再次保存。没有明确的模式。在SQL中添加列并填充后,现在只需在json文档(所有文档)中添加一个字段。所有迁移的文档都应具有此字段。旁注:如果(在迁移过程中)文档可以由另一个进程更新,事情就不会变得复杂了。这需要特殊处理(如果是这种情况,请阅读有关CAS的内容)


要获取所有相关的文档键,需要定义一个视图并进行查询。它超出了这个答案的范围(并且有很好的文档记录)。一旦拥有了所有密钥,您只需逐一迭代并更新它们。

我不知道目前有任何官方工具可以帮助数据模型迁移,但根据您使用的SDK,有一些有用的代码片段(例如,在java中)

现在你必须自己写剧本。基本流程如下:

  • 确保所有文档都有一个
    model\u version
    属性,该属性在每次迁移后递增
  • 迁移之前,请更新您的应用程序代码,以便它可以处理旧的和新的
    模型\u版本
    ,并以新模型编写新文档
  • 编写一个脚本,遍历bucket中的所有旧模型文档(您需要一个发出文档键的视图),进行所需的更新,增加
    model\u version
    并保存文档

在高并发性环境中,良好的错误处理和监控非常重要,例如,您可以有一个视图来统计每个
模型\u版本中的文档数量。本质上,您的问题分为两部分:

  • 查找所有需要更新的文档
  • 检索和更新所述文档
  • 您可以通过以下两种方式之一来完成此操作:使用提供文档ID的视图,或使用DCP流从bucket中获取所有文档。视图只提供文档的ID,因此您基本上迭代所有ID,然后使用常规键值方法检索、更新和存储每个ID。另一方面,DCP协议为您提供实际的文档

    使用视图的优点是,它的实现非常简单,可以与任何语言SDK一起使用,并且它允许您围绕流程编写自己的逻辑,使其更加健壮和安全。缺点是必须为此构建一个视图,而且如果数据不断更改,则必须立即检索整个视图结果,因为如果尝试使用偏移量翻页视图,结果的顺序可能会更改,从而使数据的快照不一致

    使用DCP对所有文档进行流式处理的优点是,即使数据不断变化,也可以保证获得一致的数据快照,而且可以直接将整个文档作为流的一部分获取,因此不需要单独检索,只需更新并存储回数据库即可。缺点是它目前只在JavaSDK中实现,被认为是一种实验性的特性。有关简单的实现,请参见
    UPDATE UserProfile
    SET Car = TO_ARRAY(Car),
    LastVisit = NOW_STR();