Cassandra架构设计

时间:2012-09-25 21:55:09

标签: nosql cassandra hector

我正在继续探索Cassandra,我想创建Student< =>课程关系类似于RDBMS上的多对多。

在查询方面,我将使用以下查询;

  1. 检索学生注册的所有课程。
  2. 检索所有报名参加特定课程的学生。
  3. 假设我创建了Column Families。一个用于课程,另一个用于学生。

    CREATE COLUMN FAMILY student with comparator = UTF8Type AND key_validation_class=UTF8Type and column_metadata=[ 
    {column_name:firstname,validation_class:UTF8Type} 
    {column_name:lastname,validation_class:UTF8Type}
    {column_name:gender,validation_class:UTF8Type}];
    
    
    CREATE COLUMN FAMILY course with comparator = UTF8Type AND key_validation_class=UTF8Type and column_metadata=[ 
    {column_name:name,validation_class:UTF8Type} 
    {column_name:description,validation_class:UTF8Type}
    {column_name:lecturer,validation_class:UTF8Type}
    {column_name:assistant,validation_class:UTF8Type}];
    

    现在我该怎么办?

    我应该使用courseID:studentId CompisiteKey创建第三列系列吗?如果是,我可以使用Hector仅通过一个(左或右)复合键组件进行查询吗?

    请帮忙。

    更新:

    根据建议,我创建了以下架构:

    学生:

    CREATE COLUMN FAMILY student with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;
    

    然后我们将添加一些数据:

    set student['student.1']['firstName']='Danny'
    set student['student.1']['lastName']='Lesnik'
    set student['student.1']['course.1']=''
    set student['student.1']['course.2']='';
    

    为课程创建列族:

    CREATE COLUMN FAMILY course with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;
    

    添加一些数据:

    set course['course.1']['name'] ='History'
    set course['course.1']['description'] ='History Course'
    set course['course.1']['name'] ='Algebra'
    set course['course.1']['description'] ='Algebra Course'
    

    最后学生在课程中:

    CREATE COLUMN FAMILY StudentInCourse with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;
    

    添加数据:

    set StudentInCourse['studentIncourse.1']['student.1'] =''; 
    set StudentInCourse['studentIncourse.2']['student.1'] =''; 
    

1 个答案:

答案 0 :(得分:1)

我在下面定义了一个数据模型,但是更容易先描述对象模型,然后深入到行模型中,所以从PlayOrm的角度来看,你会有

public class Student {
  @NoSqlId
  private String id;
  private String firstName;
  private String lastName;
  @ManyToMany
  private List<Course> courses = new ArrayList(); //constructing avoids nullpointers
}

public class Course {
  @NoSqlId
  private String id;
  private String name;
  private String description
  @ManyToOne
  private Lecturer lecturer;
  @ManyToMany
  private CursorToMany students = new CursorToManyImpl();
}

我本可以在课程中使用List,但我担心如果有太多学生多年,多年和几年学习课程,我可能会获得OutOfMemory。现在,让我们跳转到PlayOrm所做的事情,如果你愿意,你可以做类似的事情。

单个学生排看起来像这样

rowKey(the id in above entity) = firstName='dean',
lastName='hiller' courses.rowkey56=null, courses.78=null, courses.98=null, courses.101=null

这是我们有很多列的广泛行,名称为'fieldname','rowkey to actual course'

课程行更有趣......因为用户认为加载单个课程的学生可能会导致内存不足,他使用的光标在循环时只加载500个。

在这种情况下,PlayOrm将支持两个课程。 Sooo,让我们把我们的用户排在上面,他当然是rowkey56所以让我们来描述那个课程

rowkey56 = name='coursename', description='somedesc', lecturer='rowkey89ToLecturer'

然后,学生的某个索引表中还有另一行(这是一个非常宽的行,因此可以支持数百万学生)

indexrowForrowkey56InCourse = student34.56, student39.56, student.23.56.... 
into the millions of students

如果您希望课程的学生人数超过数百万,那么您需要考虑分区是否使用playOrm。如果你需要,PlayOrm会为你做分区。

注意:如果你不知道hibernate或JPA,当你加载上面的Student时,它会加载一个代理列表,所以如果你开始循环遍历这些课程,它会回到noSQL商店并加载课程,所以你不必;)。

对于Course,它会加载一个未填写的代理讲师,直到您访问讲座,如lecturer.getName()。如果你调用讲授.getId(),它不需要加载讲师,因为它已经从课程行中有了。

编辑(更多细节):PlayOrm有3个索引表Decimal(存储double,float等和BigDecimal),Integer(long,short等,BigInteger和boolean)和String索引表。当您使用CursorToMany时,它将使用其中一个表,具体取决于键的FK类型。它还将这些表用于它的Scalable-SQL语言。它在CursorToMany上使用单独行的原因只是因为客户端在读取行时没有得到OutOfMemory,因为toMany在某些情况下可能有一百万个FK。然后CursorToMany从该索引行批量读取。

后, 迪安