无法向(猫鼬)对象添加其他元素
Posted
技术标签:
【中文标题】无法向(猫鼬)对象添加其他元素【英文标题】:Can not add additional element to (mongoose) object 【发布时间】:2019-09-04 10:25:15 【问题描述】:我有一个带有 api 的 nodejs express 应用程序,用于从 mongodb 数据库返回数据。这是我的猫鼬模型:
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 时,后端内的这个函数被调用:
const bookingsListByMonth = (req, res) =>
const year = ("0000" + req.params.year).slice(-4)
const month = ("0000" + req.params.month).slice(-2)
const dateOfMonth = `$year$month01`
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
:
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"
,但它们没有。这是输出:
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
正如 cmets 建议的那样,我尝试使用 let bookings = [ tags: ["Essen"]];
作为测试数据。在这里有效。输出是:
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'
所以我想这与我的猫鼬模型限制添加任何其他字段有关。但是,如果我把
console.log("EXTENSIBLE " + Object.isExtensible(bookings))
res
.status(200)
.json(processBookings(bookings));
进入我的bookingsListByMonth
函数,我得到:
EXTENSIBLE true
所以理论上我应该可以向bookings
对象添加一些东西?
作为一种解决方法,我将timestamp2
字段添加到我的猫鼬模型中:
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 对象?如果因为是猫鼬模型而无法修改,如何制作可编辑的副本?
【问题讨论】:
不,代码按预期工作...顺便说一下,您的代码也会更改singleTagBookings
中的对象,因此,您可以改用 .forEach
- 是数组singleTagBookings
sealed 也许?
如果不是用正确的代码和数据更新问题,你一定会收到错误singleTagBookings.map is not a function
对象未密封。可悲的是我没有收到错误。我已经用完整的代码更新了我的问题。
正如@JaromandaX 报告的那样,代码工作正常 - 尝试复制它并使用let bookings = [ tags: ["Essen"]];
获取测试数据。请注意,bookings
数组的 input 版本正在更新,不得冻结或密封。
@traktor53 或设为不可扩展
【参考方案1】:
查询返回的文档是限制添加新字段的 mongoose 文档。为了将 mongoose 文档转换为纯 javascript 对象,mongoose 中有一个方法/选项 lean - https://mongoosejs.com/docs/tutorials/lean.html。
查找查询看起来像这样
bookingMongooseModel
.find(
timestamp:
$gt: start,
$lt: end
)
.sort( timestamp: 1 )
.lean()
此外,猫鼬提供了可配置的选项供您在定义架构时进行设置。例如, new Schema(.., timestamps: true);将在您的文档中创建两个字段 createdAt 和 updatedAt。有关更多信息,请参阅此处的选项部分 https://mongoosejs.com/docs/guide.html#options
【讨论】:
【参考方案2】:只需使用 toObject() 函数将您的 mongoose 对象转换为标准 javascript 对象。然后您将能够修改数据/添加新字段/更改数据类型:
const processBookings = (bookings) =>
bookings = bookings.map(function(e)return e.toObject(););
...
【讨论】:
【参考方案3】: singleTagBookings.map((item) =>
item.timestamp2 = "123"
return item
)
我认为这是你的问题..
-
map返回一个新数组,所以需要赋值给一个变量
在地图回调函数中,返回一个新对象比改变它更好
所以试试这个
singleTagBookings = singleTagBookings.map((item) => (
...item,
timestamp2: "123"
))
【讨论】:
以上是关于无法向(猫鼬)对象添加其他元素的主要内容,如果未能解决你的问题,请参考以下文章