根据文档中数组元素的值和文档本身的_id更新文档

Posted

技术标签:

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

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

我的场景:

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

我需要达到的目标:

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

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

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

我尝试过的:

    Checked the docs 在 S/O 上花了一些时间,this 被证明是最相关的答案,但我无法让这个解决方案发挥作用。 交换了我对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.';
                


   

【问题讨论】:

【参考方案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 架构中的票证,因为您可以直接在票证架构中进行更新(就像我在示例开销中所做的那样),因为所有引用最终都指向它们的对象架构。

【讨论】:

谢谢你简洁的解释和代码先生。

以上是关于根据文档中数组元素的值和文档本身的_id更新文档的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose:更新特定文档数组的元素

如何根据另一个字段更新 mongodb 中的数组 dict 元素

如何根据查询从子文档数组中更新子文档字段?

MongoDB 中嵌入文档的数组元素的并发更新

核心DOM-Document:文档对象

如何使用节点 js 更新 mongo 文档中的数组元素?