查询"包含"在用户定义类型(UDT)列表上

时间:2015-03-12 14:37:15

标签: apache-spark cassandra nosql

对于数据模型,如:

create type city (
   name text,
   code int
);

create table user (
    id uuid,
    name text,
    cities list<FROZEN<city>>,
    primary key ( id )
);

create index user_city_index on user(cities);

查询为

select id, cities from user where cities contains {name:'My City', code: 10};

工作正常。但是可以查询

select id, cities from user where cities contains {name:'My City'};

并弃掉code属性,即code=<any>

这可以通过使用Spark来实现吗?

1 个答案:

答案 0 :(得分:4)

  

但是可以查询:select id, cities from user where cities contains {name:'My City'};

不,不是。 using a UDT个州的文档(对于UDT列name):

  
      
  1. 过滤用户定义类型列的数据。创建索引,然后运行条件查询。在Cassandra 2.1.x中,您需要列出name子句中WHERE列的所有组件
  2.   

因此,查询cities UDT集合将需要city类型的所有组件。

我确信有一种方法可以在Spark中查询,但我会给你一个基于Cassandra的答案。基本上,创建一个定义/索引的附加列表列只是为了保存城市名称列表,并在其上运行CONTAINS。更好的方法是将city类型反规范化为查询表(usersbycity),使用PRIMARY KEY定义,如PRIMARY KEY(cityname, citycode, userid),并使用除user表之外的那个按城市名称和代码(或城市名称)支持查询。

请记住,当表格专门设计为适合您的查询模式时,Cassandra效果最佳。二级索引是为了方便,而不是性能。尝试扩充一个表以支持多个查询是RDBMs数据建模方法(通常在Cassandra中不能很好地工作)。而不是一个表可以很好地为一个查询提供服务,通常最终只有一个表可以很好地处理多个查询。

编辑您的问题:

1)“拥有长群集密钥是否可以接受?”

目前我无法找到关于此的明确声明,但我认为这里更大的问题是如何在“引擎盖下”存储/使用群集密钥。实质上,每个聚类键值都附加到每个列值(以便更快地检索)。显然,如果你有很多这样的东西,那就会占用磁盘空间(这些日子并没有太大的担忧......如果是的话,你可以使用COMPACT STORAGE指令来解决这个问题。)

如果你有很多,最终可能会影响性能。我可以仔细检查这个,然后再回复你。我不会去...说...... 100个聚类键。但我不认为10是一个大问题。我知道我用7或8创建了模型,它们表现得很好。

2)“如果存在与用户相关的其他非规范化表(如usersbyhobby,usersbybookread等),如何将来自这些表的过滤组合到来自userbycity的过滤器到一个查询中,因为c *中没有JOIN?”

您无法在查询时将它们组合在一起。您可以做的是,如果您发现您的查询需要同时来自usersbyhobby,usersbybookread和usersbycity的用户数据;是创建一个包含所有数据的非规范化表。根据您的查询需求,您可能需要以不同的方式订购PRIMARY KEY,在这种情况下,您需要创建与要提供特定查询的表一样多的表。

另一种选择是进行单独查询并在客户端管理它们。客户端JOIN被认为是Cassandra反模式,所以我会谨慎使用它。这完全取决于您的应用程序的需求,以及您是否希望将大部分时间用于数据建模/管理或客户端处理。老实说,我更愿意让客户端保持尽可能简单。