【问题标题】:Couchbase n1ql - NEST foreign document using indexesCouchbase n1ql - 使用索引的 NEST 外部文档
【发布时间】:2021-12-20 17:45:38
【问题描述】:

我正在尝试创建一个 N1QL 查询,该查询将返回客户端列​​表并嵌入 API 密钥数组。这是我的设置:

{
    "Client-a3c1c7f8r89732": {
        "type": "Client",
        "id": "a3c1c7f8r89732",
        "name": "Cognito Inc"
    },
    "Client-z6cc6f4r6feer5": {
        "type": "Client",
        "id": "z6cc6f4r6feer5",
        "name": "Some Corp"
    },
    "ApiKey-3846516546897987": {
        "type": "ApiKey",
        "key": "3846516546897987",
        "client_id": "a3c1c7f8r89732"
    },
    "ApiKey-98765164865351321": {
        "type": "ApiKey",
        "key": "98765164865351321",
        "client_id": "a3c1c7f8r89732"
    },
    "ApiKey-646546846546549887": {
        "type": "ApiKey",
        "key": "646546846546549887",
        "client_id": "a3c1c7f8r89732"
    }
}

可用索引

CREATE INDEX `idx-client-query` ON `primary`(`type`,`name`,`id`) WHERE (`type` = "Client")
CREATE INDEX `idx-apikey-query` ON `primary`(`type`,`client_id`,`key`) WHERE (`type` = "ApiKey")

所需的 N1QL 查询输出

[
    {
        "id": "a3c1c7f8r89732",
        "name": "Cognito Inc",
        "api_keys": [
            {
                "key": "3846516546897987"
            },
            {
                "key": "98765164865351321"
            },
            {
                "key": "646546846546549887"
            }
        ]
    },
    {
        "id": "z6cc6f4r6feer5",
        "name": "Some Corp",
        "api_keys": []
    }
]

到目前为止我已经尝试过

  • 使用 ANSI RIGHT OUTER JOIN 检索没有 api 键的客户端(查询结果需要重新处理以嵌套键)。出于某种原因,它只检索具有密钥的客户端。
  • 使用 ANSI NEST,如下所示,但我没有得到任何结果
SELECT client.name, client.id, api_key.* as api_keys
FROM `primary` client
INNER NEST `primary` api_key ON client.id = api_key.client_id
WHERE client.type = 'Client' AND api_key.type = 'ApiKey'

任何类似问题的帮助或链接将不胜感激,谢谢:)

【问题讨论】:

标签: couchbase n1ql


【解决方案1】:

我认为您与NEST 走在正确的轨道上

这就是我所做的:

SELECT c.id, c.name, ARRAY { x.`key` } FOR x IN a END AS api_keys
FROM `prim` c
LEFT NEST `prim` a ON c.id = a.client_id
WHERE c.type = "Client";

我添加了一个索引:

CREATE INDEX `adv_client_id` ON `prim`(`client_id`)

您可能想要LEFT NEST,因为您想要的结果包括一个没有分配 API 密钥的客户端。

ARRAY { } 语法只会将键提取到您想要的结果中,但您可以使用 SELECT c.id, c.name, a AS api_keys . . . 并获取 ApiKey 文档中的所有值。但我认为无论哪种方式都需要新索引。

此外,您不需要过滤 api_key.type,因为您只是加入 API 密钥。

我尝试运行您的 NEST 查询,但出现语法错误(而您说您没有结果),所以我不能确定为什么它没有返回任何内容(我使用的是 Couchbase 7 仅供参考)

【讨论】:

  • 感谢您的回答!建议的查询部分有效,但需要几分钟才能执行,并且由于通用 adv_client_id 索引,所有包含 client_id 属性的文档也会返回。
【解决方案2】:
CREATE INDEX ix1 ON default (id, name) WHERE type = "Client";
CREATE INDEX ix2 ON default (client_id, `key`) WHERE type = "ApiKey";

CB 7.0

使用相关子查询。子查询生成数组

SELECT c.id, c.name,
       (SELECT RAW a.`key`
        FROM default AS a
        WHERE a.type = "ApiKey" AND a.client_id = c.id) AS api_keys
FROM default AS c
WHERE c.type = "Client" AND c.id IS NOT NULL;

CB Pre-7.0

在 7.0 之前,相关子查询有限制(需要 USE KEYS)。所以使用 JOIN 和聚合(它可以在两边都使用覆盖,而 NEST 不会使用覆盖)。

SELECT c.id, c.name, ARRAY_AGG(a.`key`) AS api_keys
FROM default AS c
LEFT JOIN default AS a ON a.type = "ApiKey" AND a.client_id = c.id
WHERE c.type = "Client" AND c.id IS NOT NULL
GROUP BY c.id, c.name;

使用提示尝试 Hash JOIN

apis WITH (SELECT a1.client_id, ARRAY_AGG(a1.`key`) AS api_keys
           FROM default AS a1
           WHERE a1.type = "ApiKey" AND a1.client_id IS NOT NULL
           GROUP BY a1.client_id)
SELECT c.id, c.name, a.api_keys
FROM default AS c
JOIN apis AS a ON a.client_id = c.id
WHERE c.type = "Client" AND c.id IS NOT NULL;

如果数据大小合理

apiobj WITH (OBJECT v.client_id:v.api_keys
             FOR v IN (SELECT a1.client_id, ARRAY_AGG(a1.`key`) AS api_keys
                       FROM default AS a1
                       WHERE a1.type = "ApiKey" AND a1.client_id IS NOT NULL
                       GROUP BY a1.client_id)
             END)
SELECT c.id, c.name, apiobj.[c.id] AS api_keys
FROM default AS c
WHERE c.type = "Client" AND c.id IS NOT NULL;

【讨论】:

  • 谢谢! CB Pre-7.0 为我做到了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多