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

时间:2015-09-29 10:19:21

标签: couchbase nosql

我来自对象关系数据库背景,我了解Couchbase是无模式的,但数据迁移仍将在应用程序开发时发生。

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

但是在文档中,我们说json Document UserProfile:

UserProfile
{
  "Owner": "Rich guy!",
  "Car": ["Cool car", "Another car"],
  "LastVisit": "2015-09-29"
}

我们可能希望在那里添加最后一个访问字段,允许用户拥有多个汽车,因此新的更新文档将变为如下:

var element = '<div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title" id="panel_title">Demo</h3></div><div class="panel-body"><div id=print_received_table></div></div></div>';


$('#result').append(element);

但为了便于维护,我希望所有其他UserProfile文档都遵循相同的格式,将“Car”字段作为数组。

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

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

这样做迁移的好方法是什么?

5 个答案:

答案 0 :(得分:2)

基本上,您的问题分为两部分:

  1. 查找需要更新的所有文件。
  2. 检索和更新所述文件。
  3. 您可以通过以下两种方式之一执行此操作:使用提供文档ID的视图,或使用DCP流从存储桶中获取所有文档。该视图仅为您提供文档的ID,因此您基本上遍历所有ID,然后使用常规键值方法检索,更新和存储每个ID。另一方面,DCP协议为您提供实际文档。

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

    使用DCP流式传输所有文档的优势在于,即使数据不断变化,您也可以保证获得一致的数据快照,并且您可以直接将整个文档作为流,所以你不需要单独检索它 - 只需更新并存储回数据库。缺点是它目前只在Java SDK中实现,被认为是一个实验性功能。有关简单的实现,请参阅this blog

    第三种 - 对SQL用户来说最方便 - 这样做的方法是通过Couchbase 4中引入的N1QL查询语言。它与SQL中的预期data manipulation commands相同,因此您基本上可以按UPDATE myBucket SET prop = {'field': 'value'} WHERE condition = 'something'的方式发出命令。这样做的好处非常明显:它既可以同时查找和更新文档,又无需编写任何一行程序代码。缺点是DML命令被认为是&#34; beta&#34;在Couchbase的4.0版本中,如果数据集太大,那么由于某些时候超时,它可能实际上不起作用。当然,首先需要使用Couchbase 4.0这一事实。

答案 1 :(得分:1)

我目前还不知道任何有助于数据模型迁移的官方工具,但根据您使用的SDK,有一些有用的代码段(请参阅例如java中的bulk updates)。

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

  • 确保所有文档都具有model_version属性,并在每次迁移后递增。
  • 在迁移之前更新您的应用程序代码,以便它可以处理新的model_version,以便在新模型中编写新文档。
  • 编写一个脚本,遍历存储桶中的所有旧模型文档(需要一个发出文档密钥的视图),进行所需的更新,增加model_version并保存文档。

在高并发环境中,拥有良好的错误处理和监控非常重要,例如,您可以使用一个视图来计算每个model_version中的文档数量。

答案 2 :(得分:0)

如果我理解正确,这里的关键是获取并随后更新每个CB文档&#39;。这可以通过视图完成,前提是您了解视图只是“最终一致”。 (与强烈一致的读/写动作不同)。

如果(在迁移时)没有新文档添加到您的存储桶,那么您的视图将是最新的,并应返回要迁移的整个文档集。容易。

另一方面,如果新文档继续写入您的存储桶,并且需要迁移这些文档,那么您将不得不不断运行迁移代码来捕获所有这些新文档(因为视图不会返回它们)直到它更新,几秒钟后。)

在第二种情况下,在迁移过程中,您的存储桶将包含异构的文档集合:一些已经迁移的文档,一些即将迁移的文档以及一些您的视图未被查看过的文档&# 39; (因为它们最近被添加)并且只有在重新运行迁移代码后才会迁移。

要使迁移过程高效,您需要找到一种方法来区分已迁移的项目和尚未迁移的项目。您可以使用其版本号&#39;为每个文档添加字段。并在迁移期间更新它。您的视图应定义为仅选择版本号较旧的文档&#39;并忽略已经迁移的项目。

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

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

实际更新很简单:您检索文档并使用新格式再次保存。没有明确的架构。一旦你在SQL中添加了列并填充了它,你现在只需在json-doc(所有文档)中添加一个字段。所有迁移的文档都应该包含此字段。附注:如果(当您正在迁移时)文档可以由另一个进程更新,则事情变得更加复杂。这需要特殊处理(如果是这样的话,请大读CAS)。

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

答案 3 :(得分:0)

使用N1QL,Couchbase提供与RDBMS或对象关系数据库中相同的模式迁移功能。对于您问题中的示例,您可以将以下查询放在迁移脚本中:

UPDATE UserProfile
SET Car = TO_ARRAY(Car),
LastVisit = NOW_STR();

这会将存储桶中的所有文档迁移到新架构。请注意,Couchbase中的update语句提供文档级原子性,而不是语句级原子性。但由于此更新是幂等的(可重复的),如果遇到错误,您可以多次运行它。注意:类似于David上面回答的最后一段。

答案 4 :(得分:0)

您可以使用Couchmove,这是一个像Flyway DB一样工作的java迁移工具。

您可以使用此工具执行N1QL查询,以迁移文档并跟踪更改。