如何通过用户定义类型的字段过滤cassandra查询

rei*_*neh 5 user-defined-types cassandra frozen-columns frozen

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

    create type fullname ( firstname text, lastname text );
Run Code Online (Sandbox Code Playgroud)

我也有这张桌子.

    create table people ( id UUID primary key, name frozen <fullname> );
Run Code Online (Sandbox Code Playgroud)

我需要过滤我的查询以了解姓jolie的所有人.我该如何从这个表中查询.以及如何在cassandra中过滤和查询?我知道我可以删除fullname类型并将firstname和lastname添加到主表,但它是我想要做的样本.我必须具有全名类型.

shu*_*tty 7

简短回答:您可以使用二级索引按全名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'};
Run Code Online (Sandbox Code Playgroud)

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

create table fname_index (name frozen <fullname> primary key, id uuid);
Run Code Online (Sandbox Code Playgroud)

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

  • 对整个PK值(firstname + lastname)进行哈希处理,得到的数字定义了存储行的分区.
  • 对于该分区,您的行将附加到memtable(后来在磁盘上刷新到SSTable,按键排序的文件)
  • 当你只想通过PK的一部分查询时(比如仅通过名字),C*无法猜测要查找的分区(因为它无法计算整个fullname的哈希码,因为lastname是未知的) ,因为您的匹配可以在任何需要全表扫描的分区中的任何位置.C*明确禁止这些扫描,所以你别无选择:)

建议的解决方案:

  • 将UDT拆分为firstname和lastname等基本部分,并在其上设置二级索引.
  • 使用Cassandra 3.0和物化视图功能(实际上强制cassandra维护部分UDT的自定义索引)
  • 重新审视您的数据模型不那么严格(当没有人强迫您使用UDT时,他们没有帮助)