首页 > 解决方案 > 根据文档中数组元素的值和文档本身的_id更新文档

问题描述

正如问题所述,我无法让此更新操作正常工作。

我的场景:

我有一个Event,一个Ticket和一个TicketPurchase。和具有Event数组作为属性。TicketPurchaseTicket

我需要达到的目标:

  1. 更新from true/false的票证数组中validated特定的属性。TicketTicketPurchase

  2. total_quantity将主表中同一张票的属性从1.递减Event。(a中的所有票TicketPurchase都是主表中票的副本Event

作为一名程序员,我几乎所有的经验都花在了使用 MySQL 上,所以我仍然是 NoSQL 世界的初学者。

我试过的:

  1. 检查了文档
  2. 在 S/O 上花了一些时间,被证明是最相关的答案,但我无法让这个解决方案发挥作用。
  3. 交换了我对 and 的用法id_id将运算符$set放入和取出 ' ' 标记,以及所有其他类似的配置,什么都不会。

票务.js

const TicketSchema = new Schema({
type : {type: String},
total_quantity : {type: Number},
price : {type: String},
limit_per_order: {type: Number},
start_date: {type: Date},
end_date: {type: Date},
description: {type: String},
validated: {type: String, default: 'false'}
});

事件.js

const EventSchema = new Schema({

title: {type: String},
location: {type: String},
start_date: {type: Date},
start_time: {type: String},
end_date: {type: Date},
end_time: {type: String},
description: {type: String},
organizer_name: {type: String},
organizer_about: {type: String},
cover_picture: {type: String},
tickets: [{type: Schema.Types.ObjectId, ref: 'Ticket'}],
access_code: {type: String, default: shortid.generate}

});

ticketPurchase.js

const TicketPurchaseSchema = new Schema({
user: {type: Schema.Types.ObjectId, ref: 'User'},
event: {type: Schema.Types.ObjectId, ref: 'Event'},
tickets: [{type: Schema.Types.ObjectId, ref: 'Ticket'}],
time_stamp: {type: Date}

});

更新.js

for(var x of ticketPurchase.tickets){
                //console.log(x);

                if(x.id === ticket_id && x.validated === 'false'){
                    console.log('ticket not validated. Update');

                    TicketPurchase.update(
                        {_id: ticket_purchase_id, 'tickets._id': ticket_id},
                        {'$set':{
                            'tickets.$.validated': 'true'
                        }},
                        function (err){
                            console.log('updated validated');
                            if(err){console.log(err);}
                        }
                    );

                    Event
                    .update({_id: event_id, "tickets._id": x.id},
                    {$inc : {"tickets.$.total_quantity" : -1}});

                    console.log('updated ticket.total_qty');

                    payload['success'] = 'true';

                }else if(x.id === ticket_id && x.validated === 'true'){
                    console.log('ticket validated');
                    payload['success'] = 'false';
                    payload['message'] = 'Ticket already validated.';
                }


   }

标签: javascriptnode.jsmongoose

解决方案


首先,这是一个简短的示例,说明如何避免循环并仅使用 mongoose 方法完成所有操作:

TicketPurchase.findById(purchaseId, (err, ticketPurchase) => {

    Ticket.update({ _id: { $in: ticketPurchase.tickets }, _id: ticket_id, validated: 'false' },
        { $set: { validated: 'true' }, $inc: { total_quantity: -1 } }, 
        (err, outcome) => { 
            console.log(`The number of validated tickets for the Purchase #${purchaseId} is ${outcome.nModified}`); 
    }); 
});

在这里,它在同一操作中完成所有操作:找到属于购买但尚未验证的票,然后将验证的属性设置为“真”并减少数量。最后,您将获得修改记录的总数。

In your example I can't see that you've populated your tickets in the purchaseTicket. To iterate through ticket objects in the manner you wrote, you'd be compelled to populate it for their parent entity since the property ticketPurchase.tickets contains only references. The expression would look like: TicketPurchase.findById(purchaseId).populate('tickets').then(purchase => { ... }) Where purchase has the property tickets filled up with its ticket objects instead of merely id objects.

Adding to that, you seem not to have to update tickets in the Event schema since you can do it directly in the Ticket schema (just like I did in my example overhead) since all the references eventually point out to their objects in the schema.


推荐阅读