【问题标题】:Updating a doc based on the value of an array element in the doc and the _id of the doc itself根据文档中数组元素的值和文档本身的_id更新文档
【发布时间】:2019-03-23 10:38:10
【问题描述】:

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

我的场景:

我有一个Event、一个Ticket 和一个TicketPurchaseEventTicketPurchase 具有 Ticket 数组作为属性。

我需要达到的目标:

  1. TicketPurchase 的票证数组中特定Ticketvalidated 属性从真/假更新。

  2. 从主表Event 中的1. 减少同一票证的total_quantity 属性。(TicketPurchase 中的所有票证都是主表Event 中票证的副本)

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

我尝试过的:

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

ticket.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'}
});

event.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}

});

update.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.';
                }


   }

【问题讨论】:

    标签: javascript node.js mongoose


    【解决方案1】:

    首先,这是一个简短的示例,说明如何避免循环并仅使用 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}`); 
        }); 
    });
    

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

    在您的示例中,我看不到您已在 purchaseTicket 中填充了您的票。要以您编写的方式遍历票证对象,您将不得不为其父实体填充它,因为属性 ticketPurchase.tickets 仅包含引用。表达式看起来像:TicketPurchase.findById(purchaseId).populate('tickets').then(purchase => { ... }) 其中purchase 的属性tickets 填充了它的票证对象,而不仅仅是id 对象。

    除此之外,您似乎不必更新 Event 架构中的票证,因为您可以直接在票证架构中进行更新(就像我在示例开销中所做的那样),因为所有引用最终都指向它们的对象架构。

    【讨论】:

    • 谢谢你简洁的解释和代码先生。
    猜你喜欢
    • 1970-01-01
    • 2015-12-22
    • 2016-03-12
    • 2013-06-22
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    相关资源
    最近更新 更多