Couchbase n1ql - 使用索引的 NEST 外部文档
Couchbase n1ql - NEST foreign document using indexes
我正在尝试创建一个 N1QL 查询,该查询将 return 一个客户端列表并嵌入一个 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'
对于类似问题的任何帮助或 link 将不胜感激,谢谢 :)
我认为你在 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 查询,但我遇到了语法错误(而你说你没有结果),所以我不能确定为什么它没有 return 任何东西(我使用的是 Couchbase 7,仅供参考)
CREATE INDEX ix1 ON default (id, name) WHERE type = "Client";
CREATE INDEX ix2 ON default (client_id, `key`) WHERE type = "ApiKey";
CB 7.0
使用相关子查询。子查询生成 ARRAY
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 7.0 之前
在pre 7.0中,关联子查询有限制(需要USE KEYS)。所以使用 JOIN 和聚合(它可以在两边使用覆盖 vs 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;
或
尝试使用提示进行哈希连接
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;
我正在尝试创建一个 N1QL 查询,该查询将 return 一个客户端列表并嵌入一个 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'
对于类似问题的任何帮助或 link 将不胜感激,谢谢 :)
我认为你在 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 查询,但我遇到了语法错误(而你说你没有结果),所以我不能确定为什么它没有 return 任何东西(我使用的是 Couchbase 7,仅供参考)
CREATE INDEX ix1 ON default (id, name) WHERE type = "Client";
CREATE INDEX ix2 ON default (client_id, `key`) WHERE type = "ApiKey";
CB 7.0
使用相关子查询。子查询生成 ARRAY
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 7.0 之前
在pre 7.0中,关联子查询有限制(需要USE KEYS)。所以使用 JOIN 和聚合(它可以在两边使用覆盖 vs 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;
或
尝试使用提示进行哈希连接
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;