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

时间:2015-01-12 19:45:06

标签: mongodb cassandra cql cassandra-2.0

我是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中对此进行建模?

1 个答案:

答案 0 :(得分:1)

由于我有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 ,我会将评论创建为user defined type(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键为commentid。这样,您可以快速获取应用程序端的所有键和/或值。在任何情况下,这将返回给定photoalbumid的所有照片,以及任何评论。

我会以类似的方式解决查询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';

这将返回所有相册与&#34;系列&#34;标签。请注意,这是上面使用的tags set<text>的非规范化结构,这意味着相册在其中包含的每个标记中都有一个条目。我考虑过可能在tags set<text>上重用其中一个先前的查询表和二级索引(因为Cassandra现在允许集合上的索引),但是二级索引通常不能很好地执行。而且,您仍然必须对当前相册中的每个代码执行查询(使用SELECT并且IN关键字已知效果不佳。

对于前两个查询,我会创建特定的表来存储like / views / comments计数,如下所示:

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

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

相关问题