在规划 Cassandra 模式时,了解您需要查询的内容是最重要的考虑因素之一,如果不是最重要的考虑因素之一。Cassandra 旨在处理大量写入。
根据您要实现的其他功能,您可能需要创建额外的列族或完全替换这些列族,以便以最优化 cassandra 查询的方式存储数据。
此外,我建议尽可能多地将数据本地存储在 cassandra 中。我不会将 JSON 对象加载到胖字符串列中。至少在cassandra中直接存储相关数据,比如点赞值等。
您有两个域模型,用户和歌曲,以及要存储的三类数据:
- 评论
- 喜欢/不喜欢/收藏
- 查看/下载
您详细说明了更新算法所需的一些功能查询:
- 检查用户是否已经喜欢该项目
- 检查用户之前是否不喜欢该项目
- 如果他确实不喜欢,则删除该条目
- 现在获取当前喜欢
- 现在更新项目本身,设置新的喜欢计数
- 使用 cassandra 计数器,这两个步骤可以同时发生
- 更新包含所有喜欢该项目的用户的 CF
可以满足这些查询要求的模式如下。
首先,我们将为User 和 Song定义 CF ,它们都使用 UUID 作为键。
create column family users with comparator=UTF8Type
and column_metadata=[{column_name: user_name, validation_class: UTF8Type, index_type: KEYS},
{column_name: json_data, validation_class: UTF8Type}];
create column family songs with comparator=UTF8Type
and column_metadata=[{column_name: user_name, validation_class: UTF8Type, index_type: KEYS},
{column_name: json_data, validation_class: UTF8Type}];
二级索引有助于按用户名检索用户行。有关性能注意事项,请参阅此内容。
可以使用每个评论的 UUID 对评论进行建模,如下所示:
create column family comments with comparator = 'UTF8Type'
and column_metadata=[{column_name: user, validation_class: UUIDType, index_type: KEYS},
{column_name: song, validation_class: UUIDType, index_type: KEYS},
{column_name: timestamp, validation_class: DateType},
{column_name: comment, validation_class: UTF8Type}];
由于用户的喜欢和不喜欢是互斥的,我们可以使用一个列族来存储用户的所有歌曲喜欢/不喜欢。如果您将“收藏”限制为暗示喜欢,我们可以只用这个来完成所有三个。使用用户的 UUID 作为行键,歌曲的 UUID 作为列键,列值为 0 => 无值,1 => 不喜欢,2 => 喜欢,3 => 喜欢。
create column family user_likes with comparator = 'UUIDType'
and default_validation_class = IntegerType;
现在剩下的就是跟踪每首歌曲的总喜欢、不喜欢、收藏、观看和下载。我们可以使用Cassandra 的计数器列类型在一个 CF 中完成此操作。使用歌曲的 UUID 作为 CF 键。
create column family song_data with default_validation_class=CounterColumnType
and column_metadata=[{column_name: likes},
{column_name: dislikes},
{column_name: favorites},
{column_name: views},
{column_name: downloads}];