如何在Cassandra中设计表,其中必须通过列表<varchar>?</varchar>查找行

时间:2014-06-03 14:10:04

标签: database-design cassandra cql

鉴于我在Cassandra中持有以下对象:

Foo数组:

{
    "id":1,
    "name": "this is a name",
    "bundleFields" : [
        "bundleByMe",
        "me2",
        "me also",
    ]
},
{
    "id":2,
    "name": "anotherName",
    "bundleFields" : [
        "bundleByMe",
        "me2",
        "me also",
    ]
},
{
    "id":3,
    "name": "thridName",
    "bundleFields" : [
        "differentBundleCriteria"
    ]
}

我想查询类似SELECT * FROM FOO where bundleFields = ["...", "..."]的内容。

这显然不起作用,因为list<>的查询是不可能的(没有主键)。

这是我目前拥有的架构:

CREATE TABLE IF NOT EXISTS Foo (
    id int,
    name varchar,
    bundleFields list<varchar>,
    PRIMARY KEY(id)
);

我能想象的唯一解决方案是另一个表,其中PRIMARY KEY包含bundleFields-Array的连接值,这将允许bundleString查找:

CREATE TABLE IF NOT EXISTS fooByBundleString (
    bundleString varchar,
    fooId int,
    PRIMARY KEY(bundleString)
);

这是cassandra中这个问题的推荐方法。

必须序列化/反序列化bundleFields-array的想法对我来说感觉不对。

感谢您的建议!


编辑:由于@rs_atl建议表fooByBundleString的正确DDL应该是(注意PRIMARY KEY中的附加fooId):

CREATE TABLE IF NOT EXISTS fooByBundleString (
    bundleString varchar,
    fooId int,
    PRIMARY KEY(bundleString, fooId)
);

创建一个覆盖索引,否则就不可能为不同的fooId存储相同的bundleString。

1 个答案:

答案 0 :(得分:1)

正如您所描述的那样创建索引是正确的解决方案。但是它应该是覆盖索引,这意味着您希望复制查询中实际需要返回的任何值。否则,您最终会在应用程序中进行分布式连接,这非常昂贵。通常,偏好非规范化数据模型到归一化关系模型。这与您最喜欢的RDBMS中必须执行的操作基本相同,以便快速进行查询。不同之处在于您必须在应用程序中管理索引;卡桑德拉不会为你做这件事。