代码之家  ›  专栏  ›  技术社区  ›  saimonsez

在卡桑德拉处理一对多问题

  •  3
  • saimonsez  · 技术社区  · 7 年前

    给定以下简化域模型:

    列车行程

    • id uuid
    • 列车名称字符串(一天内唯一)
    • 行程日期日期
    • ...

    旅程车站

    • 站点uuid
    • 到达时间戳
    • 出发时间戳
    • ...

    与此相关:

    • 1列车行程有n个行程站

    使用此查询要求:

    • 给定车站的所有列车行程, 包括所有行程站 ,在给定的时间范围内离开。

    这个查询应该如何在Cassandra中建模?

    我在想这样的事情:

    CREATE TABLE departures_by_station (
        date_of_yourney date,
        train_name varchar,
        station uuid,
        arrival timestamp,
        departure timestamp,
        primary key((date_of_journey, station), train_name, departure)
    );
    
    SELECT * from departures_by_station 
    WHERE date_of_journey = '2018-01-02' AND station = 'Paris' AND departure ...;
    

    这将不起作用,因为它会导致部分列车行程-除了请求的行程站之外,所有行程站都将丢失。 更糟糕的是;出发时间可能经常变化。我无法使用新的离开时间更新此表,因为它是一个群集键。

    有什么想法或提示可以解决这个问题吗?我想我缺少一些基本的东西,但我对nosql世界非常陌生。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Alex Ott    7 年前

    首先,它可能不是最理想的解决方案(需要计算分区大小等)。如果您可以使用TTL使“旧”数据过期,那么我考虑使用如下内容:

    CREATE TABLE departures_by_station (
       station uuid,
       departure timestamp,
       train_name varchar,
       arrival timestamp,
       statitions list<uuid>
       primary key(station, departure, train_name)
    );
    

    在这种情况下,您将拥有所谓的“宽”分区—每个旅程站点一个分区,并且因为您将出发作为集群键,所以可以对其进行范围搜索。但如果大量数据过期,则需要经常对表执行“修复”,以清除墓碑(删除标记),因为这可能会影响读取性能。

    此外,为了避免进行多次查找,您需要将旅程中所有站点的信息放在每一行中——我这样写的 list<uuid> ,但它可以更好地建模为用户定义的类型,因此可以包含站点名称和其他信息。

    您的代码还应该为特定列车的旅程中的每个车站生成一个条目。

    P、 我建议参加DS220(数据建模)课程 DataStax Academy .