已解决(底部的解决方案)。
我是MongoDB的新手,但我遇到了问题。 我正在尝试将集合“内部”(或附加)更新为另一个集合,您可以在下面找到我的架构。 如何更新特定的Booking.review?每个评论均由不同的来源(用户ID)创建。当然,我不想更新或删除其他用户的先前评论,它只需要更新特定的来源(用户)评论。
const ReviewsSchema = new Schema({
comment: {
type: String
},
value: {
type: Number
},
// User who rates, can be the buyer or the provider.
source: {
type: Schema.Types.ObjectId,
ref: 'User',
required: [ true, 'A reference to a user who rates (source) must exist']
},
// User who was rated, can be the buyer or the provider.
target: {
type: Schema.Types.ObjectId,
ref: 'User',
required: [ true, 'A reference to a user who is reated (target) must exist']
},
});
const bookingSchema = new Schema( {
buyer: {
type: Schema.Types.ObjectId,
ref: 'User',
required: [ true, 'A reference to a user must exist']
},
status: {
type: String // ['pending', 'confirmed', 'finished']
},
reviews: [ReviewsSchema],
// When service start
updated_at: {
type: Date
},
});
要更新或创建新评论,我正在这样做:
objForUpdate.reviews = {
"value" : body.review.value,
"comment" : body.review.comment,
"source": body.review.source,
"target": body.review.target};
}
objForUpdate = objForUpdate;
var ObjectId = require('mongodb').ObjectID;
await Booking.updateOne(
{ "_id" : ObjectId(body.booking_id),
"reviews.source": body.review.source},
{ $set : objForUpdate },
{ upsert: true } // Creates an attributes if it does not exist.
);
但是这会更新收藏集中的评论[0],我需要使用source = user_id更新评论或创建一个新评论(如果此源没有任何评论)。
我仍然有问题,但是我认为我离一次旅行还差几个小时:),现在我收到了这个错误消息:
Mongoose: bookings.findOneAndUpdate({ _id: ObjectId("5ef2fd2242c1e25bae12345c"), 'reviews.source': ObjectId("5ef01cc677608e0d44911234")}, { '$setOnInsert': { __v: 0 }, '$set': { 'reviews.$.value': 2, 'reviews.$.comment': 'hello trying 5' }}, { upsert: true, remove: false, projection: {}, returnOriginal: false })
(node:44862) UnhandledPromiseRejectionWarning: MongoError: The positional operator did not find the match needed from the query.
这是当前的更新查询:
const filter = { '_id' : ObjectId(body.booking_id), 'reviews.source': body.review.source};
const update = {
$set: {
'reviews.$.value' : body.review.value,
'reviews.$.comment' : body.review.comment
}
};
const afterUpdate: any = await Booking.findOneAndUpdate(filter, update, {
new: true,
upsert: true // Make this update into an upsert
});
好吧,我一直在努力了解如何解决此问题,并且我意识到,如果数据库中已经存在带有元素“ source”的reviews对象数组(子文档),则不会收到错误消息: em> MongoError:位置运算符未从查询中找到所需的匹配项 。”。但是如果数组“ reviews”还不存在,该怎么做?我已经向更新查询添加了 upsert:true ,这还不够吗? ?
{
"_id" : ObjectId("5ef2fd2242c1e25bae41631c"),
"requesters" : 1,
"location" : "1234,4545",
"reviews" : [
{
"source" : ObjectId("5ef01cc677608e0d44916974"),
"target" : ObjectId("5eef83248649890585e6f19e")
},
{
"source" : ObjectId("5eef83248649890585e6f19e"),
"target" : ObjectId("5ef01cc677608e0d44916974"),
"comment" : "hello 8",
"value" : 2
}
],
"__v" : 0
}
我这样解决了它: 首先,当创建新预订时,我创建了一个空的reviews对象数组,然后将源值和目标值推送到每个元素,然后使用下面的代码,它可以正常工作。可能不是最佳解决方案,因为我真的很希望能够在添加新评论时(而不是在创建预订时)创建评论子文档数组(如果尚不存在),但是至少可以使用此解决方案它正在工作。
const reviews_empty = [
{'source': String(req.body.buyer), 'target': String(provider_data.user)},
{'source': String(provider_data.user), 'target': String(req.body.buyer)}
];
createBooking(req.body).then( async (booking: any) => {
console.log('booking', booking);
await Booking.updateOne(
{ _id: booking._id },
{ $push: { reviews: reviews_empty } }
);
return res.json({
code: 200,
data: {
'_id': booking._id
}
});
}).catch( ( err: any ) => {
return res.json({
code: 404,
message: `error message ${err}`
});
});
var ObjectId = require('mongodb').ObjectID;
const filter = {
$and: [
{"_id" : ObjectId(body.booking_id)},
{"reviews.source": ObjectId(body.review.source)}
]
};
const update = {
$set: {
"reviews.$.value" : body.review.value,
"reviews.$.comment" : body.review.comment
}
};
// Then now I can update the reviews, because the source item already exits.
const afterUpdate: any = await Booking.updateOne(filter, update, {
new: true,
upsert: true // Make this update into an upsert
});
if (afterUpdate.n === 1) {
resolve(body.review);
}
非常感谢!