首页 > 解决方案 > MongoDB。从对象 ID 更改类型

问题描述

我有收藏衬衫,其中有一个“图像”字段,目前是对另一个收藏的引用:

...
    images: {
        type: [{
            type: Schema.Types.ObjectId,
            ref: 'Image'
        }]
    }, 

我需要将该类型更改为这样的对象:

const ImageSchema = new Schema({
    cloudImage: String,
    imageName: String,
});

 ...
    images: {
        type: ImageSchema
    }, 

问题:在我的数据库中,我已经有大约 1000 个文档,其中 ObjectId 存储在图像字段中。由于文档不多,所以我决定对所有文档执行循环并转换数据并再次将其存储在新的模型结构中。问题是,当我从“衬衫”获取“图像”时,mongo 会返回:

[ { _bsontype: 'ObjectID',
    id: <Buffer 5f 8a fe 45 0b cc ae 21 5a 9f 2c 6b> } ]

和错误:

CastError: Cast to ObjectId failed for value "{ _bsontype: 'ObjectID',
  id: <Buffer 5f 8a fe 45 0b cc ae 21 5a 9f 2c 6b> }" at path "_id" for model "Image"

我猜这是因为存储了一个 ObjectId,并且我将集合字段图像更改为另一种类型。如果我再次输入 [ObjectId] 类型,它会返回 id。

我执行此操作的脚本是:

async function updateShirtImages() {

    const shirts = await Shirt.find({});

    shirts.forEach(async (shirt) => {

        
        const imagesArray = shirt.images;
        console.log(IMAGES ARRAY =>, imagesArray)
        //Result: IMAGES ARRAY ==> [ { _bsontype: 'ObjectID',
        //id: <Buffer 5f 8a fe 45 0b cc ae 21 5a 9f 2c 6b> } ]
         
        imagesArray.forEach(async (image) => {
            console.log(image)
            const databaseImage = await Image.findOne({ _id: image }); // Here the error
            const updatedDataImageShirt = {
                cloudImage: databaseImage.cloudImage,
                imageName: databaseImage.imageName,
            };
            shirt.images.push(updatedDataImageShirt);
            await shirt.save();
        })
    })
}

谢谢你!

编辑 ==> 解决了问题,当我在所有衬衫中执行 find() 方法时应用 .lean() 以获得 POJO。

标签: mongodb

解决方案


is valid在查询图像集合之前检查图像 ObjectId ,

async function updateShirtImages() {
    try {
        const shirts = await Shirt.find({}).exec();
        for (const shirt of shirts) {
            for (const image of shirt.images) {
                if (image && mongoose.Types.ObjectId.isValid(image)) {
                    const databaseImage = await Image.findOne({ _id: image }).exec();
                
                    if (databaseImage !== null) {
                        const updatedDataImageShirt = {
                            cloudImage: databaseImage.cloudImage,
                            imageName: databaseImage.imageName,
                        };
                    
                        shirt.images.push(updatedDataImageShirt);
                        await shirt.save();
                    }
                }
            }
        }
        
    } catch (err) {
        console.error(err);
        throw err;
    }
}

推荐阅读