不能向(猫鼬)对象添加额外的元素 [英] Can not add additional element to (mongoose) object
问题描述
我有一个带有 api 的 nodejs express 应用程序,用于从 mongodb 数据库返回数据.这是我的猫鼬模型:
I have a nodejs express application with an api to return data from a mongodb database. This is my mongoose model:
const bookingSchema = new mongoose.Schema({
timestamp: {
type: Date,
default: Date.now,
required: true
},
tags: {
type: [String],
required: true
},
amount: {
type: Number,
required: true
},
type: {
type: String,
required: true,
enum: ['expense', 'income']
}
})
当我使用路径 /api/bookings/listbymonth/2019/1
调用 api 时,会调用后端内部的此函数:
When I'm calling the api with the path /api/bookings/listbymonth/2019/1
this function inside the backend gets called:
const bookingsListByMonth = (req, res) => {
const year = ("0000" + req.params.year).slice(-4)
const month = ("0000" + req.params.month).slice(-2)
const dateOfMonth = `${year}${month}01`
const start = moment(dateOfMonth).startOf("month")
const end = moment(dateOfMonth).endOf("month")
bookingMongooseModel
.find({
timestamp: {
$gt: start,
$lt: end
}
})
.sort({ timestamp: 1 })
.exec((err, bookings) => {
if (!bookings) {
return res
.status(404)
.json({
"message": "booking not found"
})
} else if (err) {
return res
.status(404)
.json(err)
}
res
.status(200)
.json(processBookings(bookings));
})
}
我不想简单地返回 json 数据,而是想对数据进行预处理并制作一个不错的时间戳和货币字段.这就是 json 数据通过额外的 processBookings
函数运行的原因.为了测试,我尝试添加另一个字段 timestamp2: 123
:
Instead of simply returning the json data, I want to preprocess the data and make a nice timestamp and currency field. That's why the json data runs through an additional processBookings
function. For testing I tried to add another field timestamp2: 123
:
const processBookings = (bookings) => {
console.log("Bookings unsorted: \n" + bookings + "\n")
const mainTags = [
"Essen",
"Essen gehen",
"Notwendiges",
"Luxus",
]
let bookingsProcessed = []
mainTags.forEach((tag) => {
let singleTagBookings = bookings.filter(
booking => booking.tags.includes(tag)
)
singleTagBookings.map((item) => {
item.timestamp2 = "123"
return item
})
let message = null;
if (singleTagBookings.length === 0) {
message = "No bookings found";
}
bookingsProcessed.push({
name: tag,
bookings: singleTagBookings,
message: message
})
});
console.log("Bookings sorted:")
bookingsProcessed.forEach((item) => {
console.log(item)
})
return bookingsProcessed
}
bookings
数组中的对象应该有另一个属性 timestamp2: "123"
,但它们没有.这是输出:
The objects in the bookings
array should have another property timestamp2: "123"
, but they don't. Here's the output:
Bookings unsorted:
{ tags: [ 'Luxus', 'voluptatem', 'atque', 'qui', 'sunt' ],
_id: 5cb2c9e1ff6c9c6bef95f56f,
timestamp: 2019-01-06T08:53:06.945Z,
amount: 68.02,
type: 'expense',
__v: 0 },{ tags: [ 'Essen gehen', 'ut', 'unde', 'et', 'officiis' ],
_id: 5cb2c9e1ff6c9c6bef95f56e,
timestamp: 2019-01-09T20:35:06.411Z,
amount: 33.77,
type: 'income',
__v: 0 }
Bookings sorted:
{ name: 'Essen', bookings: [], message: 'No bookings found' }
{ name: 'Essen gehen',
bookings:
[ { tags: [Array],
_id: 5cb2c9e1ff6c9c6bef95f56e,
timestamp: 2019-01-09T20:35:06.411Z,
amount: 33.77,
type: 'income',
__v: 0 } ],
message: null }
{ name: 'Notwendiges',
bookings: [],
message: 'No bookings found' }
{ name: 'Luxus',
bookings:
[ { tags: [Array],
_id: 5cb2c9e1ff6c9c6bef95f56f,
timestamp: 2019-01-06T08:53:06.945Z,
amount: 68.02,
type: 'expense',
__v: 0 } ],
message: null }
正如评论中建议我尝试使用 let bookings = [ {tags: ["Essen"]}];
作为测试数据.在这里它有效.输出为:
As in the comments suggested I tried to use let bookings = [ {tags: ["Essen"]}];
as test data. Here it works. The output is:
Bookings unsorted:
[object Object]
Bookings sorted:
{ name: 'Essen',
bookings: [ { tags: [Array], timestamp2: '123' } ],
message: null }
{ name: 'Essen gehen',
bookings: [],
message: 'No bookings found' }
{ name: 'Notwendiges',
bookings: [],
message: 'No bookings found' }
{ name: 'Luxus', bookings: [], message: 'No bookings found' }
所以我想这与我的猫鼬模型限制添加任何其他字段有关.但是如果我把
So I guess it has something to do with my mongoose model restricting to add any additional field. However If I put
console.log("EXTENSIBLE " + Object.isExtensible(bookings))
res
.status(200)
.json(processBookings(bookings));
进入我的 bookingsListByMonth
函数,我得到:
into my bookingsListByMonth
function I get:
EXTENSIBLE true
所以理论上我应该能够向 bookings
对象添加一些东西?
So in theory I should be able to add something to the bookings
object?
作为一种解决方法,我将 timestamp2
字段添加到我的猫鼬模型中:
As a workaround I added the timestamp2
field to my mongoose model:
const bookingSchema = new mongoose.Schema({
timestamp: {
type: Date,
default: Date.now,
required: true
},
timestamp2: {
type: String,
default: null
},
tags: {
type: [String],
required: true
},
amount: {
type: Number,
required: true
},
type: {
type: String,
required: true,
enum: ['expense', 'income']
}
})
这有效,但是它在我的数据库中添加了一个额外的无用数据字段.如何修改从 mongodb 返回的 bookings
json 对象?如果因为是猫鼬模型而无法修改,如何制作可编辑的副本?
This works, however it adds an additional useless data field into my database. How can I modify the bookings
json object returned from the mongodb? If I can't modify it because it is a mongoose model, how can I make a copy that is editable?
推荐答案
从查询返回的文档是限制添加新字段的猫鼬文档.为了将 mongoose 文档转换为纯 JavaScript 对象,mongoose 中有一个方法/选项 lean - https://mongoosejs.com/docs/tutorials/lean.html.
Documents returned from queries are mongoose documents which restricts addition of new fields. In order to convert mongoose documents into plain JavaScript objects there is a method/option lean in mongoose - https://mongoosejs.com/docs/tutorials/lean.html.
查找查询看起来像这样
bookingMongooseModel
.find({
timestamp: {
$gt: start,
$lt: end
}
})
.sort({ timestamp: 1 })
.lean()
此外,mongoose 提供了可配置的选项供您在定义架构时进行设置.例如, new Schema({..}, {timestamps: true});将在您的文档 createdAt 和 updatedAt 中创建两个字段.有关更多信息,请参阅此处的选项部分 https://mongoosejs.com/docs/guide.html#options
Additionally, mongoose provides configurable options for you to set while defining schema. For instance, new Schema({..}, {timestamps: true}); would create two fields in your document createdAt and updatedAt. For more information see Options section here https://mongoosejs.com/docs/guide.html#options
这篇关于不能向(猫鼬)对象添加额外的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!