我一直在为产品目录系统开发Node.JS / MongoDB后端,我遇到了一个奇怪的错误。
首先,我从产品系列中加载产品信息。此产品包含诸如名称,描述以及文件上载ID列表之类的信息,这些ID指向字符串数组中产品的图像。 然后,我为每个上传ID加载每张照片的信息。然后我用一组文件信息对象替换上传ID字符串数组。 但是,当我输出结果产品对象时,图像列表是一个表示JavaScript的字符串列表,就好像它们是用代码编写的一样。
// products.controller.js
async function populateImageInformation(productRecord) {
let imageInfo = [];
for(let uploadId of productRecord.images) {
let imageData = await File.getByUploadId(uploadId);
imageInfo.push(imageData);
console.log(typeof imageData); // => object
}
console.log(typeof imageInfo); // => object
console.log(typeof imageInfo[0]); // => object
productRecord.images = imageInfo;
console.log(typeof productRecord.images); // => object
console.log(typeof productRecord.images[0]); // => string
return productRecord;
}
async function getAll(req, res, next) {
try {
let productRecords = await Product.find({});
for(let productRecordI in productRecords) {
productRecords[productRecordI] = await populateImageInformation(productRecords[productRecordI]);
}
res.json(productRecords);
} catch (e) {
next(e);
}
}
Mongoose模式文件:
// file.model.js
getByUploadId: function(uploadId) {
return this.findOne({
uploadId
});
}
我不明白当我将productRecord.images
属性设置为imageInfo
时,数组中的值突然变为值的字符串表示形式。
该字符串不包含JSON,而是包含一个人类可读的字符串表示,表示如何将对象硬编码为JavaScript。这些字符串根本无法解析为JSON。 JSON期望密钥用双引号括起来,而生成的JavaScript代码却没有。
有没有理由这样做?我从未见过这种情况。
答案 0 :(得分:1)
问题是由 mongoose架构引起的,它们保护模型是您在架构中声明的类型。通过find返回的对象是一个猫鼬模型,当您更新任何值时,它们会进行类型检查。
让我们来看看你的情景。我创造了一个例子。见下文
const mongoose = require('mongoose');
const db = require('./db');
const Schema = mongoose.Schema;
const productSchema = new Schema({
name: {type: String},
images: [String] // Note schema have array of string
});
const productModel = mongoose.model('product', productSchema);
db.connect().then(() => {
//find record from productSchema
return productModel.find({})
.then((productRecords) => { //productRecords - don't forget is a mongoose model object
// productRecords from db [{"name":"gilette","images":["idx","idy"],"_id":"5ac324c4fad317265b9df226","__v":0}]
//TRIAL A
for (let productRecordI in productRecords) {
productRecords[productRecordI] = populateImageInformation(productRecords[productRecordI]);
}
console.log(typeof productRecords[0].images[0]); //=> string;
//SOLUTION for the problem is copy mongoose data without reference
//TRIAL B
productRecords = JSON.parse(JSON.stringify(productRecords));
for (let productRecordI in productRecords) {
productRecords[productRecordI] = populateImageInformation(productRecords[productRecordI]);
}
console.log(typeof productRecords[0].images[0]); //=> Object;
});
//just a mock function change images to object
function populateImageInformation(productRecord) {
imageInfo = [];
for (let uploadId of productRecord.images) {
let imageData = {name: uploadId};
imageInfo.push(imageData);
console.log(typeof imageData); // => object
}
productRecord.images = imageInfo;
return productRecord;
}
}).catch((err) => {
console.log('err', err);
});