Cassandra如何统计非集合列中包含指定文本的行数?
报错原因
Cassandra的CONTAINS条件仅支持set、list、map三类集合类型列,你的genres字段是text类型的普通字符串,因此会抛出Cannot use CONTAINS on non-collection column genres错误,属于语法层面的硬限制,无法直接绕过。
解决方案
按不同使用场景选对应方案即可:
- 临时统计、数据量不大(百万行以内):客户端侧计算
不需要改表结构、不需要建索引,直接查询全表的genres字段,在代码侧拆分标签后统计,实现成本最低。Python参考实现:
from cassandra.cluster import Cluster
替换为实际的Cassandra连接地址
cluster = Cluster(['127.0.0.1'])
session = cluster.connect('movielens')
comedy_count = 0
for row in session.execute("SELECT genres FROM data_movies"):
if 'Comedy' in row.genres.split('|'):
comedy_count += 1
print(comedy_count)
- 不改动表结构、需要直接通过CQL查询:LIKE+SASI索引 Cassandra 3.4+版本支持SASI自定义索引实现字符串包含匹配,先给genres列建索引: ```sql CREATE CUSTOM INDEX genres_contains_idx ON movielens.data_movies (genres) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = { 'mode': 'CONTAINS', 'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer', 'case_sensitive': 'true' };
索引创建完成后,用以下查询覆盖Comedy在标签串的所有位置(单独存在、开头、中间、结尾),避免误匹配名称带Comedy的其他标签:
SELECT COUNT(*) FROM movielens.data_movies WHERE genres = 'Comedy' OR genres LIKE 'Comedy|%' OR genres LIKE '%|Comedy' OR genres LIKE '%|Comedy|%' ALLOW FILTERING;
如果确认数据集不存在名称包含Comedy的非目标标签,可以直接简化为WHERE genres LIKE '%Comedy%'。
- 高频按电影类型做查询统计:改造表结构为集合类型
这是长期使用的最优方案,将genres字段类型从text改为set<text>,数据导入时将原|分隔的字符串拆分为标签集合存入。改造后可以直接使用CONTAINS语法,查询性能远高于字符串模糊匹配:
SELECT COUNT(*) FROM movielens.data_movies WHERE genres CONTAINS 'Comedy' ALLOW FILTERING;
内容的提问来源于stack exchange,提问作者NNN
相关产品推荐
相关产品推荐

