如何为 Cassandra 数据库建模 mongodb 集合(迁移)



我是Cassandra的新手,正在尝试将我的应用程序从MongoDB迁移到Cassandra

我在MongoDB中有以下集合

PhotoAlbums
[
  {id: oid1, title:t1, auth: author1, tags: ['bob', 'fun'], photos: [pid1, pid2], views:200 }
  {id: oid2, title:t2, auth: author2, tags: ['job', 'fun'], photos: [pid3, pid4], views: 300 }
  {id: oid3, title:t3, auth: author3, tags: ['rob', 'fun'], photos: [pid2, pid4], views: 400 }
  ....
]
Photos
[
 {id: pid1, cap:t1, auth: author1, path:p1, tags: ['bob','fun'], comments:40, views:2000, likes:0 }
 {id: pid2, cap:t2, auth: author2, path:p2, tags: ['job','fun'], comments:50, views:50, likes:1, liker:[bob] }
 {id: pid3, cap:t3, auth: author3, path:p3, tags: ['rob','fun'], comments:60, views: 6000, likes: 0 }
 ...
]
Comments
[
  {id: oid1, photo_id: pid1, commenter: bob, text: photo is cool, likes: 1, likers: [john], replies: [{rep1}, {rep2}]}
  {id: oid2, photo_id: pid1, commenter: bob, text: photo is nice, likes: 1, likers: [john], replies: [{rep1}, {rep2}]}
  {id: oid3, photo_id: pid2, commenter: bob, text: photo is ok, likes: 2, likers: [john, bob], replies: [{rep1}]}
]

查询:

  • 查询 1:显示热门专辑列表(基于赞数)

  • 查询 2:显示讨论最多的专辑列表(基于评论)

  • 查询 3:显示给定作者的所有专辑的列表用户页面

  • 查询 4:显示包含所有照片和所有评论的相册(拉取相册详细信息,显示所有照片的照片缩略图相册,显示所选照片的所有评论

  • 查询 5:显示基于当前相册标签的相关相册

鉴于上述模式和要求,我应该如何在 Cassandra 中对此进行建模?

由于我对Cassandra和Mongo都有经验,所以我会尝试一下。 这里棘手的部分是MongoDB允许对索引和查询进行非常宽松的限制。 Cassandra在这方面有一个更棘手的模型,但如果创建正确,它应该可以快速执行。 此外,计算照片或相册上的喜欢/观看次数/评论方面也可能变得棘手,因为您需要使用 Cassandra 的 counter 类型(这有其自身的挑战)。

免责声明:其他人可能会以不同的方式解决这些问题。 如果我的第一次尝试没有成功,我可能会选择以不同的方式解决它们。 但这就是我要开始的。

为了满足查询 3,我将创建一个名为 PhotoAlbumsByAuthor查询表并像这样查询它:

CREATE TABLE PhotoAlbumsByAuthor (
 photoalbumid uuid,
 title text,
 author text,
 tags set<text>,
 photos set<uuid>,
 PRIMARY KEY(author,title,photoalbumid)
);
> SELECT * FROM photoalbumsbyauthor WHERE author='Malcolm Reynolds';

这将返回用户Malcolm Reynolds创建的所有相册,按title排序(因为标题是第一个聚类键)。

对于查询 4,我会将注释创建为用户定义类型 (UDT):

CREATE TYPE yourkeyspacename.comment (
 commenter text,
 commenttext text
);

然后我会创建一个名为 PhotosByAlbum 的查询表,并像这样查询它:

CREATE TABLE PhotosByAlbum (
 photoalbumid uuid,
 photoid uuid,
 cap text,
 auth text,
 path text,
 tags set<text>,
 comments map<uuid,frozen <comment>>,
 PRIMARY KEY(photoalbumid,photoid)
);
> SELECT * FROM PhotosByAlbum WHERE photoalbumid=a50aa80a-8714-44b4-9b97-43ec4b13daa6;

向此表添加注释时,地图的uuid键是注释 ID。 通过这种方式,您可以快速获取应用程序端的所有键和/或值。 在任何情况下,这将返回给定相册ID的所有照片以及任何注释。

我会以类似的方式解决查询 5,通过创建一个名为 PhotoAlbumsByTag 的查询表(您现在应该注意到一种模式)并像这样查询它:

CREATE TABLE PhotoAlbumsByTag (
 tag text,
 photoalbumid uuid,
 title text,
 author text,
 photos set<uuid>,
 PRIMARY KEY(tag,title,photoalbumid)
)
SELECT * FROM PhotoAlbumsByTag WHERE tag='family';

这将返回带有"家庭"标签的所有相册。 请注意,这是上面使用的tags set<text>的非规范化结构,这意味着相册在此表中将有一个条目,用于它包含的每个标记。 我想过可能重用以前的查询表之一,并在tags set<text>上使用二级索引(因为 Cassandra 现在允许对集合进行索引),但二级索引通常表现不佳。 无论如何,您仍然必须对当前专辑中的每个标签执行查询(使用带有 IN 关键字的 SELECT

也已知效果不佳)。

至于前两个查询,我会创建特定的表来存储喜欢/视图/评论计数,如下所示:

CREATE TABLE PhotoCounters (
 photoid uuid,
 views counter,
 comments counter,
 likes counter,
 PRIMARY KEY (photoid)
);
使用

counter 类型时,Cassandra 要求主键和计数器是该表中的唯一列(不能将计数器与非计数器列混合使用)。 我还会使用 Hadoop 或 Spark 以 OLAP 方式处理离线查询/报告。 希望这有帮助。

最新更新