9

如何按用户定义的类型字段过滤 cassandra 查询?我想在我的 cassandra 数据库中创建 people 表,所以我在我的 cassandra 数据库中创建这个用户定义类型。

    create type fullname ( firstname text, lastname text );

我也有这张桌子。

    create table people ( id UUID primary key, name frozen <fullname> );

我需要过滤我的查询以了解所有姓氏为 jolie 的人。我如何从这个表中查询这个。以及在 cassandra 中的过滤和查询完全如何?我知道我可以删除全名类型并将名字和姓氏添加到主表,但这是我想要做的一个示例。我必须有全名类型。

4

1 回答 1

11

简短回答:您可以使用二级索引按全名 UDT 进行查询。但是您不能仅通过 UDT 的一部分进行查询。

// create table, type and index
create type fullname ( firstname text, lastname text );
create table people ( id UUID primary key, name frozen <fullname> );
create index fname_index on your_keyspace.people (name);

// insert some data into it
insert into people (id, name) values (now(), {firstname: 'foo', lastname: 'bar'});
insert into people (id, name) values (now(), {firstname: 'baz', lastname: 'qux'});

// query it by fullname
select * from people where name = { firstname: 'baz', lastname: 'qux' };

// the following will NOT work:
select * from people where name = { firstname: 'baz'};

这种行为的原因是 C* 二级索引的实现方式。通常,它只是由 C* 维护的另一个隐藏表,在您的情况下定义为:

create table fname_index (name frozen <fullname> primary key, id uuid);

实际上,您的辅助键和主键在此表中交换。因此,您的案例被简化为一个更普遍的问题“为什么我不能只通过 PK 的一部分进行查询?”:

  • 整个 PK 值(名字+姓氏)被散列,结果数字定义了存储你的行的分区。
  • 对于那个分区,你的行被附加到一个内存表(然后在磁盘上刷新到 SSTable,一个按键排序的文件)
  • 当您只想按 PK 的一部分(例如仅按名字)查询时,C* 无法猜测要查找的分区(因为它无法计算整个全名的哈希码,因为姓氏未知) ,因为您的匹配项可以在任何需要全表扫描的分区中的任何位置。C* 明确禁止这些扫描,所以你别无选择 :)

建议的解决方案:

  • 将您的 UDT 拆分为名字和姓氏等基本部分,并在其上具有二级索引。
  • 使用带有物化视图功能的 Cassandra 3.0(实际上强制 cassandra 为您的部分 UDT 维护自定义索引)
  • 重新审视你的数据模型,使其不那么严格(当没有人强迫你在没有帮助的地方使用 UDT 时)
于 2015-11-23T12:39:03.463 回答