You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

N1QL查询返回嵌套数组,如何展平为一维数组用于IN子句?

问题描述

我有agent-activities文档结构如下,包含emailInteractions和voiceInteractions两个字符串数组字段:

{
  "agentId": "agent2",
  "date": "2022-08-30",
  "metaData": {
    "documentCreationDate": "2022-08-30T15:49:21Z",
    "documentVersion": "1.0",
    "expiry": 1662479361
  },
  "emailInteractions": [
    "0c99ea2a-c235-4c5a-a0bd-aeffba559bca",
    "12846a9d-7cc1-4755-b527-cd8aee9d2de4"
  ],
  "voiceInteractions": [
    "1c99ea2a-c235-4c5a-a0bd-aeffba559bca",
    "22846a9d-7cc1-4755-b527-cd8aee9d2de4"
  ]
}

尝试用以下N1QL查询两个数组的并集,结果返回嵌套数组(数组的数组),无法直接在主查询的IN子句中使用:

SELECT ARRAY_UNION(IFMISSINGORNULL(emailInteractions, []), IFMISSINGORNULL(voiceInteractions, [])) AS ids
FROM `agent-activities`
WHERE agentId = "agent2"

返回结果:

[
  [
    "12846a9d-7cc1-4755-b527-cd8aee9d2de4",
    "22846a9d-7cc1-4755-b527-cd8aee9d2de4",
    "0c99ea2a-c235-4c5a-a0bd-aeffba559bca",
    "1c99ea2a-c235-4c5a-a0bd-aeffba559bca"
  ]
]

我的主查询是合并voice-interactions和email-interactions的数据,需要根据指定agentId过滤对应的interactionId,当前写法因子查询返回嵌套数组导致IN子句无法正确匹配,需要将嵌套数组展平为一维数组,或优化WHERE IN子句写法:

SELECT lst.*
FROM (
    SELECT iv.id AS interventionId,
           vi.direction,
           vi.channel,
           vi.startDate AS startDate,
           vi.id AS interactionId,
           vi.customerProfileId
    FROM `voice-interactions` AS vi
    UNNEST vi.distributions AS dv
    UNNEST dv.interventions AS iv
    UNION
    SELECT ie.id AS interventionId,
           ei.direction,
           ei.channel,
           ei.startDate AS startDate,
           ei.id AS interactionId,
           ei.customerProfileId
    FROM `email-interactions` AS ei
    UNNEST ei.distributions AS de
    UNNEST de.interventions AS ie) AS lst
WHERE lst.interactionId IN (
SELECT raw ARRAY_UNION(IFMISSINGORNULL(emailInteractions, []), IFMISSINGORNULL(voiceInteractions, [])) AS ids
FROM `agent-activities`
WHERE agentId = $agentId)
ORDER BY startDate ASC
LIMIT $limit
OFFSET $offset

解决方案

方法一:展平嵌套数组,让子查询返回一维数组

在子查询中用UNNEST展开ARRAY_UNION生成的数组,配合RAW返回单个值而非数组,这样IN子句就能正确匹配:

SELECT RAW id
FROM `agent-activities`
UNNEST ARRAY_UNION(IFMISSINGORNULL(emailInteractions, []), IFMISSINGORNULL(voiceInteractions, [])) AS id
WHERE agentId = $agentId

将其代入主查询后,完整语句如下:

SELECT lst.*
FROM (
    SELECT iv.id AS interventionId,
           vi.direction,
           vi.channel,
           vi.startDate AS startDate,
           vi.id AS interactionId,
           vi.customerProfileId
    FROM `voice-interactions` AS vi
    UNNEST vi.distributions AS dv
    UNNEST dv.interventions AS iv
    UNION
    SELECT ie.id AS interventionId,
           ei.direction,
           ei.channel,
           ei.startDate AS startDate,
           ei.id AS interactionId,
           ei.customerProfileId
    FROM `email-interactions` AS ei
    UNNEST ei.distributions AS de
    UNNEST de.interventions AS ie) AS lst
WHERE lst.interactionId IN (
    SELECT RAW id
    FROM `agent-activities`
    UNNEST ARRAY_UNION(IFMISSINGORNULL(emailInteractions, []), IFMISSINGORNULL(voiceInteractions, [])) AS id
    WHERE agentId = $agentId)
ORDER BY startDate ASC
LIMIT $limit
OFFSET $offset

方法二:使用JOIN代替IN子句,优化性能

如果数据量较大,JOIN通常比IN子句性能更优。可以将agent-activities的数组展开后与主查询结果进行匹配:

SELECT lst.*
FROM (
    SELECT iv.id AS interventionId,
           vi.direction,
           vi.channel,
           vi.startDate AS startDate,
           vi.id AS interactionId,
           vi.customerProfileId
    FROM `voice-interactions` AS vi
    UNNEST vi.distributions AS dv
    UNNEST dv.interventions AS iv
    UNION
    SELECT ie.id AS interventionId,
           ei.direction,
           ei.channel,
           ei.startDate AS startDate,
           ei.id AS interactionId,
           ei.customerProfileId
    FROM `email-interactions` AS ei
    UNNEST ei.distributions AS de
    UNNEST de.interventions AS ie) AS lst
JOIN `agent-activities` aa
UNNEST ARRAY_UNION(IFMISSINGORNULL(aa.emailInteractions, []), IFMISSINGORNULL(aa.voiceInteractions, [])) AS interactionId
WHERE aa.agentId = $agentId AND lst.interactionId = interactionId
ORDER BY startDate ASC
LIMIT $limit
OFFSET $offset

也可以直接通过数组包含关系做JOIN,逻辑更简洁:

SELECT lst.*
FROM (
    SELECT iv.id AS interventionId,
           vi.direction,
           vi.channel,
           vi.startDate AS startDate,
           vi.id AS interactionId,
           vi.customerProfileId
    FROM `voice-interactions` AS vi
    UNNEST vi.distributions AS dv
    UNNEST dv.interventions AS iv
    UNION
    SELECT ie.id AS interventionId,
           ei.direction,
           ei.channel,
           ei.startDate AS startDate,
           ei.id AS interactionId,
           ei.customerProfileId
    FROM `email-interactions` AS ei
    UNNEST ei.distributions AS de
    UNNEST de.interventions AS ie) AS lst
JOIN `agent-activities` aa
ON lst.interactionId IN ARRAY_UNION(IFMISSINGORNULL(aa.emailInteractions, []), IFMISSINGORNULL(aa.voiceInteractions, []))
WHERE aa.agentId = $agentId
ORDER BY startDate ASC
LIMIT $limit
OFFSET $offset

内容的提问来源于stack exchange,提问作者Tapaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:40:30