如何按用户自定义类型中的字段过滤Cassandra查询

10

如何通过用户定义类型字段过滤Cassandra查询?

我想在我的Cassandra数据库中创建people表,因此我在我的Cassandra数据库中创建了这个用户定义类型。

    create type fullname ( firstname text, lastname text );

而且我也有这张表。

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

我需要筛选查询出所有姓Jolie的人,该如何从这个表中查询?另外,在Cassandra中如何进行过滤和查询?我知道可以删除fullname类型并将firstname和lastname添加到主表中,但这只是我想要做的示例。我必须保留fullname类型。

1个回答

12

简短回答:您可以使用二级索引通过fullname 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*维护的另一个隐藏表,在您的情况下定义为:

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

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

实际上,在这张表中,你的主键和次要键被交换了。因此,你的情况被简化为一个更普遍的问题:‘为什么我不能只查询主键的一部分?’:

  • 整个主键值(名字+姓氏)被哈希,得出的数字定义了存储行的分区。
  • 对于该分区,将在memtable中添加您的行(稍后将其刷新到SSTable上,这是按键排序的文件)
  • 当您只想通过PK的一部分进行查询(例如仅按名字查询),C*无法猜测要查找的分区(因为它无法计算出全名的哈希码,因为姓氏未知),因为您的匹配可以出现在任何分区中并需要进行全表扫描。C*明确禁止这些扫描,所以您别无选择 :)

建议的解决方案:

  • 将您的UDT拆分为基本部分,如名字和姓氏,并在其上建立辅助索引。
  • 使用具有Materialized Views功能的Cassandra 3.0(实际上是强制Cassandra为您的UDT的一部分维护自定义索引)
  • 重新审视您的数据模型,使其更加灵活(当没有人强制您在不需要的地方使用UDT时)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接