mongodb 复制子文档修改并插入相同文档中

需求:
需要复制文档中的子文档并修改某个字段插入到相同的文档中。如文档:

{ 
    "_id" : ObjectId("59b5e84d71ab5580d643d070"), 
    "modifiedOn" : ISODate("2019-04-03T14:57:22.177+0000"), 
    "modifiedBy" : "XXX", 
    "createdOn" : ISODate("2017-09-09T16:33:34.464+0000"), 
    "createdBy" : "liuyu", 
    "channelSales" : [
        {
            "platform" : "amazon", 
            "channel" : "amazon_ca", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dc1")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_uk", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dc0")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_us", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dbf")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_jp", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dbe")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_de", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dbd")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_es", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dbc")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_fr", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dbb")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_it", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39dba")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_au", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db9")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_de", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db8")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_es", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db7")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_fr", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db6")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_it", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db5")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_uk", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db4")
        }, 
        {
            "platform" : "ebay", 
            "channel" : "ebay_us", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("59b5f86aaa0ee15555a39db3")
        }, 
        {
            "platform" : "walmart", 
            "channel" : "walmart_us", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("5a4d9de2bb1aee844f03e1a6")
        }, 
        {
            "platform" : "walmart", 
            "channel" : "walmart_ca", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("5a4d9de2bb1aee844f03e1a5")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_au", 
            "saleStatus" : "T", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("5abe095bb1d48d194f6187c0")
        }, 
        {
            "platform" : "amazon", 
            "channel" : "amazon_in", 
            "saleStatus" : "A", 
            "type" : "", 
            "url" : "", 
            "remark" : "", 
            "isCaught" : "0", 
            "_id" : ObjectId("5c9af2776f3dcf04491818f2")
        }
    ], 
    "statusLevel" : "", 
    "statusType" : "", 
    "status" : "A", 
    "skuId" : "abc001", 
    "__v" : NumberInt(3)
}

需要复制:

{
    "platform" : "walmart", 
    "channel" : "walmart_us", 
    "saleStatus" : "A", 
    "type" : "", 
    "url" : "", 
    "remark" : "", 
    "isCaught" : "0", 
    "_id" : ObjectId("5a4d9de2bb1aee844f03e1a6")
}

并修改{"channel" : "walmart_us"}{"channel" : "walmart_dsv"},修改后插入原文档子文档字段。
尝试代码:

db.getCollection("0521").aggregate([{
    $unwind: "$channelSales"
}, {
    $project: {
        platform: "$channelSales.platform",
        channel: "$channelSales.channel",
        saleStatus: "$channelSales.saleStatus",
        type: "$channelSales.type",
        url: "$channelSales.url",
        remark: "$channelSales.remark",
        isCaught: "$channelSales.isCaught",
        _id: "$channelSales._id"
    }
}, {
    $match: {
        "channel": "amazon_us"
    }
}]).forEach(function(award_team) {
    if (award_team != null) {
        db.getCollection("0521").findAndModify({
            query: {
                _id: award_team._id
            },
            update: {
                $push: {
                    channelSales: [{
                        platform: award_team.platform,
                        channel: "walmart_dsv",
                        saleStatus: award_team.saleStatus,
                        type: award_team.type,
                        url: award_team.url,
                        remark: award_team.remark,
                        isCaught: award_team.isCaught,
                        _id: award_team._id
                    }]
                }
            },
            upsert: true,
        });
    }
});

但是变成新增加一个文档,请教如何处理。

阅读 1.7k
1 个回答

导致你问题的直接原因是:

$project: {
    platform: "$channelSales.platform",
    channel: "$channelSales.channel",
    saleStatus: "$channelSales.saleStatus",
    type: "$channelSales.type",
    url: "$channelSales.url",
    remark: "$channelSales.remark",
    isCaught: "$channelSales.isCaught",
    _id: "$channelSales._id"    // <--这里
}

你把_id映射成了channelSales._id,后面又用这个_id作为条件来查找文档并$push,当然会找不到。然后因为用了upsert,当然就变成新文档了。
至于怎么改,还得看你到底要做什么。从目前的数据看起来,每个channelSales元素都有一个独一无二的_id。而你上面的代码中在复制元素时同时也复制了这个_id。最后一个文档中会有两个channelSales元素的_id是一样的。这到底是不是期望的行为?我认为照常理来说最有可能的情况应该是生成新的_id。所以正确的写法应该是:

db.getCollection("0521").aggregate([{
    $unwind: "$channelSales"
}, {
    $project: {
        platform: "$channelSales.platform",
        channel: "$channelSales.channel",
        saleStatus: "$channelSales.saleStatus",
        type: "$channelSales.type",
        url: "$channelSales.url",
        remark: "$channelSales.remark",
        isCaught: "$channelSales.isCaught",
        // 删除了_id的映射,让其保持默认值,即文档的_id
    }
}, {
    $match: {
        "channel": "amazon_us"
    }
}]).forEach(function(award_team) {
    if (award_team != null) {
        db.getCollection("0521").findAndModify({
            query: {
                _id: award_team._id
            },
            update: {
                $push: {
                    channelSales: [{
                        platform: award_team.platform,
                        channel: "walmart_dsv",
                        saleStatus: award_team.saleStatus,
                        type: award_team.type,
                        url: award_team.url,
                        remark: award_team.remark,
                        isCaught: award_team.isCaught,
                        _id: new ObjectId()    // 生成一个不重复的新的_id
                    }]
                }
            },
            upsert: true,
        });
    }
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进