用猫鼬更新子文档

时间:2020-06-27 09:15:43

标签: mongodb collections

已解决(底部的解决方案)。

我是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更新评论或创建一个新评论(如果此源没有任何评论)。

注意:目前,我每次预订只能创建一个评论: enter image description here

我仍然有问题,但是我认为我离一次旅行还差几个小时:),现在我收到了这个错误消息:

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); 
        
            }

非常感谢!

0 个答案:

没有答案