如何将ObjectId数组转换为带有包含原始数组元素值的字段的嵌入式文档数组

时间:2019-07-01 17:32:46

标签: mongodb

我有一个文档集合,其中一个字段当前是ObjectId项目的数组。

{
    _id: ObjectId(...),
    user: "jdoe",
    docs: [
        ObjectId(1),
        ObjectId(2),
        ...
    ]
}
{
    _id: ObjectId(...),
    user: "jsmith",
    docs: [
        ObjectId(3),
        ObjectId(4),
        ...
    ]
}

如何更新集合中的所有文档,以将docs字段转换为包含“ docID”字段的对象数组,该字段等于原始元素值?

例如,我希望我的文档最终看起来像:

{
    _id: ObjectId(...),
    user: "jdoe",
    docs: [
        { docID: ObjectId(1) },
        { docID: ObjectId(2) },
        ...
    ]
}
{
    _id: ObjectId(...),
    user: "jsmith",
    docs: [
        { docID: ObjectId(3)},
        { docID: ObjectId(4)},
        ...
    ]
}

我希望有一个可以从shell运行的命令,例如:

db.getCollection('myCollection').update(
    {}, 
    { 
        $set: { 
            'docs.$[]: { docID: '$$VALUE'}
        }
    }, 
    {multi: true }
);

但是我不知道如何引用元素的原始值。


更新

我正在用正确的答案标记@mickl,因为它使我走上了正确的轨道。以下是我最终得出的最终汇总,如果它是对象ID的数组,则 仅更改docs字段,否则现有值保持不变,包括没有docs的文档字段。

db.getCollection('myCollection').aggregate([
    { $addFields: {
        'docs': { $cond: {
            if : { $eq: [{ $type: { $arrayElemAt: [ '$docs', 0]} }, "objectId"]},
            then: { $map: {
                input: '$docs',
                in: { tocID: '$$this'}
            }},
            else : '$docs'
        }}
    }},
    { $out: "myCollection" }
])

1 个答案:

答案 0 :(得分:1)

您可以使用$map重塑数据,并使用$out用聚合结果替换现有集合:

db.col.aggregate([
    {
        $addFields: {
            docs: {
                $map: {
                    input: "$docs",
                    in: { docID: "$$this" }
                }
            }
        }
    },
    { $out: "col" }
])