【发布时间】:2014-05-21 14:12:57
【问题描述】:
我在 Cassandra 中非常出色(我主要来自 RDBMS 背景,并在各处使用过一些 NoSQL,例如 Google 的 BigTable 和 MongoDB),并且我正在努力为我正在尝试的用例进行数据建模满足。我查看了this 和this 甚至this,但它们并不是我所需要的。
我有这张基本表:
CREATE TABLE documents (
itemid_version text,
xml_payload text,
insert_time timestamp,
PRIMARY KEY (itemid_version)
);
itemid 实际上是一个 UUID(并且对于所有文档都是唯一的),version 是一个 int(版本 0 是“第一个”版本)。 xml_payload 是完整的 XML 文档,可以变得相当大。是的,我实际上是在创建一个版本化的文档存储。
如您所见,我将两者连接起来创建了一个主键,稍后我会在解释要求和/或用例时解释我这样做的原因:
- 用户需要获得他想要的单 (1) 个文档,他知道项目 ID 和版本(不一定是最新的)
- 用户需要获得他想要的单 (1) 个文档,他知道项目 id 但不知道最新版本
- 用户需要单 (1) 个文档的版本历史记录。
- 用户需要获取他想要的文档列表(1 个或多个),他知道项目 ID 和版本(不一定是最新的)
我将编写执行用例的客户端代码,请原谅我试图与语言无关的语法
第一个很简单:
$itemid_version = concat($itemid, $version)
$doc = csql("select * from documents where itemid_version = {0};"
-f $itemid_version)
现在为了满足第 2 和第 3 个用例,我添加了下表:
CREATE TABLE document_versions (
itemid uuid,
version int,
PRIMARY KEY (itemid, version)
) WITH clustering order by (version DESC);
新记录将随着新文档和现有文档的新版本的创建而添加
现在我们有了这个(用例 #2):
$latest_itemid, $latest_version = csql("select itemid,
version from document_versions where item_id = {0}
order by version DESC limit 1;" -f $itemid)
$itemid_version = concat($latest_itemid, $latest_version)
$doc = csql("select * from documents where itemid_version = {0};"
-f $itemid_version)
还有这个(用例 #3):
$versions = csql("select version from document_versions where item_id = {0}"
-f $itemid)
对于第三个要求,我要添加另一个表:
CREATE TABLE latest_documents (
itemid uuid,
version int,
PRIMARY KEY (itemid, version)
)
为新文档插入记录,为现有文档更新记录
现在我们有了这个:
$latest_itemids, $latest_versions = csql("select itemid, version
from latest_documents where item_id in ({0})" -f $itemid_list.toCSV())
foreach ($one_itemid in $latest_itemids, $one_version in $latest_versions)
$itemid_version = concat($latest_itemid, $latest_version)
$latest_docs.append(
cql("select * from documents where itemid_version = {0};"
-f $itemid_version))
现在我希望清楚为什么我将itemid 和version 连接起来为documents 创建索引而不是创建复合键:我不能在WHERE 的WHERE 子句中使用ORSELECT
您可以假设只有一个进程会执行插入/更新,因此您无需担心一致性或隔离问题。
我在正确的轨道上吗?有很多事情不适合我……但主要是因为我还不了解 Cassandra:
- 我觉得
documents的主键应该是 (itemid, version) 的组合,但我不能满足用例 #4(从查询中返回列表)...我不可能使用由于性能下降(网络开销),每个文档都有一个单独的 SELECT 语句......或者我可以(应该)吗? - 如果事先不知道版本,则需要 2 次获取文档。可能是我必须接受的妥协,或者可能有更好的方法。
【问题讨论】: