如何使用AQL在ArangoDB中按指定属性合并集合文档
AQL实现按指定字段分组合并文档
场景说明
现有集合包含3条示例文档:
doc1 {'X':'a', 'Y':'b', 'Z':'c'} doc2 {'X':'m', 'Y':'n', 'Z':'c'} doc3 {'X':'a', 'Y':'b', 'Z':'d'}
合并规则:
- 以
X、Y字段取值为分组依据,取值完全相同的文档划入同一合并组 - 同组内除
X、Y外的所有业务字段,将所有取值去重后归集:如果仅存在1个唯一值则保留单值格式,存在多个值则存为数组 - 删除同组内所有原始文档,插入合并后的新文档;仅含1条文档的分组直接保留原内容即可
执行后期望得到的集合结果:
doc13 {'X':'a', 'Y':'b', 'Z':['c', 'd']} doc2 {'X':'m', 'Y':'n', 'Z':'c'}
实现语句
以下语句默认集合名为yourCollection,执行前请替换为实际集合名称:
// 先完成全量文档的分组聚合,避免遍历集合时同时读写产生冲突 LET groupedResult = ( FOR doc IN yourCollection // 按X、Y字段分组 COLLECT x = doc.X, y = doc.Y INTO groupItems // 聚合除X/Y和系统字段外的所有属性 LET mergedProps = MERGE( FOR prop IN ATTRIBUTES(groupItems[0].doc, true) FILTER prop NOT IN ['X', 'Y', '_id', '_key', '_rev'] LET allValues = UNIQUE(groupItems[*].doc[prop]) RETURN { // 单值保留原始格式,多值存为去重数组 [prop]: LENGTH(allValues) == 1 ? allValues[0] : allValues } ) RETURN { // 记录同组所有旧文档ID,用于后续删除 oldDocIds: groupItems[*].doc._id, // 构造合并后的新文档 mergedDoc: MERGE({X: x, Y: y}, mergedProps) } ) // 批量删除所有原始旧文档 LET removeOld = ( FOR group IN groupedResult FOR docId IN group.oldDocIds REMOVE docId IN yourCollection ) // 批量插入合并完成的新文档 FOR group IN groupedResult INSERT group.mergedDoc IN yourCollection RETURN NEW
注意事项
- 执行写操作前建议先注释掉
REMOVE和INSERT段落,单独运行groupedResult的查询逻辑,确认分组聚合结果符合预期后再执行全量语句,避免误改数据 - 语句默认对聚合字段做去重处理,如果你需要保留重复值,把
UNIQUE(groupItems[*].doc[prop])替换为groupItems[*].doc[prop]即可 - 如果需要所有聚合字段统一使用数组格式(哪怕只有一个值),将三目运算部分直接替换为
allValues即可
内容的提问来源于stack exchange,提问作者Sami Mansour
相关产品推荐
相关产品推荐

