Cassandra:如何建模列族以执行类似交叉的查询

时间:2013-07-18 09:16:41

标签: database-design cassandra intersect cql3

基本上我有三个属性:partIdmeasurementDefvalue。 每个部分(partId)由特定类型的多个度量(值)组成(measurementDef)。

格式化为树,它看起来像这样:

-part 1
  |- measurementDef 1 -> 15,86
  |- measurementDef 2 -> 19,54
-part 2
  |- measurementDef 1 -> 21,21
  |- measurementDef 3 -> 65,54
  |- measurementDef 4 -> 12,54
-part 3
   ...

现在我的问题是:我应该如何建模我的列族来做这样的事情:

SELECT partId
FROM <table>
WHERE measurementDef = xxx AND value > 10
INTERSECT
SELECT partId
FROM <table>
WHERE measurementDef = yyy AND value < 50

换句话说:我想找到所有部件,其measurementRf xxx的值高于10且measurementDef yyy的值低于50。

2 个答案:

答案 0 :(得分:1)

AFAIK,没有建模方法在单个查询中进行交集。我建议使用以下表格设计:

create table mdefparts(
    mdef int,
    value float,
    parts set<uuid>,
    primary key(mdef, value)
);

然后使用查询:

select parts from mdefparts where mdef=XXX and value > 10;
select parts from mdefparts where mdef=YYY and value < 50;

然后将第一个查询中的所有集合连接到一个集合(例如,set1)。

将第二个查询中的所有集合加入set2。

然后只是交叉set1和set2。

答案 1 :(得分:0)

可能有另一种选择。

如果阈值超出,您可以创建一个“虚拟”列,在插入过程中设置为1或0。然后,创建一个复合列索引,如下所示:

    CREATE TABLE mdefparts (
            part int,
            name text,
            val double,
            time timeuuid,
            exceeded boolean,
            PRIMARY KEY ((part, name), exceeded, time)
    );

这样可以这样工作:

    cqlsh:test> CREATE TABLE mdefparts (
            ... part int,
            ... name text,
            ... val double,
            ... time timeuuid,
            ... exceeded boolean,
            ... PRIMARY KEY ((part, name), exceeded, time)
            ... );
    cqlsh:test> 
    cqlsh:test> insert into mdefparts (part, name, val, time, exceeded) values (0, 'y', 100, 37a5de5c-efb3-11e2-99d0-f23c91aec05e, true);
    cqlsh:test> insert into mdefparts (part, name, val, time, exceeded) values (0, 'x', 100, 37a5de6c-efb3-11e2-99d0-f23c91aec05e, true);
    cqlsh:test> insert into mdefparts (part, name, val, time, exceeded) values (0, 'y', 10, 37a5de7c-efb3-11e2-99d0-f23c91aec05e, false);
    cqlsh:test> insert into mdefparts (part, name, val, time, exceeded) values (1, 'y', 1, 37a5de8c-efb3-11e2-99d0-f23c91aec05e, false);
    cqlsh:test> select * from mdefparts;

     part | name | exceeded | time                                 | val
    ------+------+----------+--------------------------------------+-----
        0 |    y |    False | 37a5de7c-efb3-11e2-99d0-f23c91aec05e |  10
        0 |    y |     True | 37a5de5c-efb3-11e2-99d0-f23c91aec05e | 100
        1 |    y |    False | 37a5de8c-efb3-11e2-99d0-f23c91aec05e |   1
        0 |    x |     True | 37a5de6c-efb3-11e2-99d0-f23c91aec05e | 100

    cqlsh:test> select * from mdefparts where name in ('x','y') and part = 0 and exceeded = true;

     part | name | exceeded | time                                 | val
    ------+------+----------+--------------------------------------+-----
        0 |    x |     True | 37a5de6c-efb3-11e2-99d0-f23c91aec05e | 100
        0 |    y |     True | 37a5de5c-efb3-11e2-99d0-f23c91aec05e | 100

这里的核心思想是将查询建模到列族中。我添加了一个timeuuid,允许随着时间的推移进行多次测量。