【问题标题】:How do you convert an array of ObjectIds into an array of embedded documents with a field containing the original array element value如何将 ObjectIds 数组转换为嵌入文档数组,其中包含原始数组元素值的字段
【发布时间】:2019-07-01 17:32:46
【问题描述】:

我有一个文档集合,其中一个字段当前是 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 字段,否则现有值保持原样,包括没有文档的文档字段。

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" }
])

【问题讨论】:

  • 你可以在这里使用$out聚合。 db.getCollection('myCollection').aggregate([ { "$addFields": { "docs": { "$map": { "input": "$docs", "in": { "docID": "$$this" } } } }}, { "$out": "newCollection" } ])

标签: mongodb


【解决方案1】:

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

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

【讨论】:

  • 谢谢@mickl。由于并非我的所有文档都有 docs 字段,因此我避免了聚合 $out 方法,因为我不想意外丢失一些原始文档。 $out 让我很紧张……期待即将到来的 $merge 阶段。我想我只需要进行几次试运行,以确保我的聚合管道包含所有文档并修改那些确实具有 docs 字段的文档。
  • @JerrenSaunders 您可以将临时集合指定为 $out 参数,验证输出,然后覆盖现有的
  • 是的,这是我目前的做法。感谢您的指导。
猜你喜欢
  • 1970-01-01
  • 2019-10-28
  • 1970-01-01
  • 2021-10-02
  • 2010-10-17
  • 2022-10-21
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
相关资源
最近更新 更多