【问题标题】:How do you extract the maximum and minimum value from a nested array in N1QL query?如何从 N1QL 查询中的嵌套数组中提取最大值和最小值?
【发布时间】:2020-08-07 21:29:13
【问题描述】:

背景

我正在运行以下查询(我知道它可能很难阅读,所以我会在之后澄清它在做什么):

SELECT *
FROM `my_bucket` AS a
    NEST (
    SELECT c.toNode, c.fromNode, d.endDateTime, d.startDateTime
    FROM `my_bucket` AS c
        JOIN (
        SELECT id, customAttributes.endDateTime, customAttributes.startDateTime
        FROM `my_bucket`
        WHERE type='airNode'
            AND customAttributes.endDateTime >= CLOCK_UTC()
            AND customAttributes.endDateTime <= DATE_ADD_STR(CLOCK_UTC(), 14, 'day')) AS d ON c.toNode = d.id
        AND c.type='relNode') b ON a.id = b.fromNode AND a.type='edNode';

本质上,这里发生的事情是我们从数据库中提取相关的 airNodes,并将它们与 relNodes.toNode = airNodes.id 的 relNodes 连接起来(toNode 和 id 是来自它们各自节点的字段)。然后,我们将这些 relAirNodes 与 edNodes 连接起来,语句返回以下结构:

[ { 'edNode':..., 'relAirNodes':[{...},{...}] },...]

所以本质上,我们得到一个对数组,其中每一对由一个 edNode 和一个 relAirNode 数组组成。

问题

relAirNodes 数组中的每个 relAirNode 都有一个 endTime 和 startTime 字段。有没有办法运行查询,使得返回结果是一个对数组,对的第一个元素是一个 editNode,对的第二个元素是一个单一的结构,数组的最小 startTime relAirNodes 和 relAirNodes 数组的最大 endTime? 换句话说,返回对象如下所示:

[ { 'edNode':..., 'relAirNodes':{'startTime':..., 'endTime':...}}, ...]

【问题讨论】:

    标签: sql database couchbase n1ql


    【解决方案1】:

    Couchbase JOINS 从左到右。如果您只查看 INNER JOINS,则只需重新排列 JOIN,以便更早地消除。

    创建此处描述的索引https://blog.couchbase.com/ansi-join-support-n1ql/

    SELECT en.*, c AS relAirNodes
    FROM (SELECT rn.fromNode, MIN(b.startDateTime) AS startDateTime, MAX(b.endDateTime) AS endDateTime
          FROM (SELECT an.id, an.customAttributes.endDateTime, an.customAttributes.startDateTime
                FROM my_bucket AS an
                WHERE an.type = "airNode"
                      AND an.customAttributes.endDateTime BETWEEN CLOCK_UTC() AND DATE_ADD_STR(CLOCK_UTC(), 14, "day")
                ) AS b
          JOIN my_bucket AS rn ON rn.type = "relNode" AND rn.toNode = b.id
          GROUP BY rn.fromNode) AS c
    JOIN my_bucket AS en ON en.type = "edNode" AND en.id = c.fromNode
    ;
    
    CREATE INDEX ix1 ON my_bucket(customAttributes.endDateTime, customAttributes.startDateTime, id) WHERE type = "airNode";
    CREATE INDEX ix2 ON my_bucket(toNode, fromNode) WHERE type = "relNode";
    CREATE INDEX ix3 ON my_bucket(id) WHERE type = "edNode";
    

    如果需要外部连接(需要 CB 6.5.0+ https://blog.couchbase.com/ansi-join-enhancements-and-ansi-merge/

    SELECT en.*, c AS relAirNodes
    FROM my_bucket AS en
    LEFT JOIN (SELECT rn.fromNode, MIN(b.startDateTime) AS startDateTime, MAX(b.endDateTime) AS endDateTime
               FROM (SELECT an.id, an.customAttributes.endDateTime, an.customAttributes.startDateTime
                     FROM my_bucket AS an
                     WHERE an.type = "airNode"
                           AND an.customAttributes.endDateTime BETWEEN CLOCK_UTC() AND DATE_ADD_STR(CLOCK_UTC(), 14, "day")
                ) AS b
               JOIN my_bucket AS rn ON rn.type = "relNode" AND rn.toNode = b.id
               GROUP BY rn.fromNode) AS c ON en.id = c.fromNode
    WHERE en.type = "edNode";
    

    还有 ARRAY_MIN()、ARRAY_MAX() 函数。例如:对象数组上的 ARRAY_MIN(relAirNodes[*].startDateTime)。

    【讨论】:

    • 当我运行它时,我收到以下错误:```“No index available for ANSI join term rn”``` :( 这是我找到的一个:forums.couchbase.com/t/no-index-available-for-ansi-join-term/…
    • 但是让我实际尝试一下 ARRAY 函数 - 这些看起来真的很有帮助!谢谢顺便说一句:)
    • 响应中的博客给出了 ANSI JOIN 的工作原理。由于全局二级索引 CREATE INDEX ix1 ON my_bucket(customAttributes.endDateTime, customAttributes.startDateTime, id) WHERE type = "airNode"; 您需要索引在 my_bucket(toNode, fromNode) 上创建索引 ix2 WHERE type = "relNode";在 my_bucket(id) WHERE type = "edNode"; 上创建索引 ix3
    • 您好,谢谢您的帮助!我用 ARRAY 函数试了一下,它奏效了!接受你的回答:)
    猜你喜欢
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多