1

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

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

  1. 检索学生注册的所有课程。
  2. 检索所有注册特定课程的学生。

假设我为列族创建。一个用于课程,另一个用于学生。

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'] =''; 
4

1 回答 1

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 将有两行支持 Course。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,直到您访问像 leller.getName() 这样的属性字段时才会填写该代理讲师。如果您调用讲师.getId(),它不需要加载讲师,因为它已经从课程行中获得了讲师。

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

后来,迪恩

于 2012-09-26T14:23:02.397 回答