创建订单时,文档具有以下架构:
{order:1,startTime:1402442830110}
订单完成后,会处理db.collection.findAndModify()
操作以设置endTime,从而产生如下文档:
{order:1,startTime:1402442830000,endTime:1402442930000}
在同一过程中,我需要设置顺序duration
,通过减去两次来计算:doc.endTime-doc.startTime
。
是否有操作员或程序可以帮助您在一次操作中执行此操作?或者我是否必须执行两个FindAndModify操作,一个用于设置返回新文档的新数据,另一个用于设置duration
字段?
答案 0 :(得分:2)
从我理解的内容,转换为SQL,你想做这样的事情
UPDATE [Order] SET
EndTime = GETDATE(),
Duration = GETDATE() - StartTime
WHERE OrderID = ''
不幸的是,MongoDB尚不支持。但是,您仍然可以通过2次更新来完成。第一个不一定是findAndModify
,findOne
就足够了。
var startTime = db.order.findOne({order: 1}).startTime;
var endTime = new Date();
db.order.findAndModify({
query: {order: 1},
update: {$set: {endTime: endTime, duration: endTime - startTime}}
});
实际上,我不认为此处的findAndModify
会为您带来除纯update
之外的任何优势,除非您想要阻止同一订单多次更新。在这种情况下,最好改变这样的条件:
var startTime = db.order.findOne({order: 1}).startTime;
var endTime = new Date();
db.order.findAndModify({
query: {order: 1, endTime: {$exists: false}},
update: {$set: {endTime: endTime, duration: endTime - startTime}}
});
在我看来,你应该有一些东西来控制订单的状态,比如订购/付款/取消......要锁定状态的订单会比{endTime: {$exists: false}}
好得多。
答案 1 :(得分:0)
您可以使用聚合框架执行此操作。以下是示例代码:
db.col.aggregate(
[
{$match:{order:1}},
{$project:{order:1, startTime:1,endTime:{$add:[new Date().getTime()]}}},
{$project:{order:1,startTime:1,endTime:1,duration:{$subtract:["$endTime","$startTime"]}}}
])
这是给定管道的执行方式:
答案 2 :(得分:0)
您的代码的第一个问题是:您使用两个不同的单元(即普通的javascript和MongoDB)来为文档添加时间戳。不是使用两个不同的程序是错误的,但在这种情况下,它们返回时间的格式不一样!
您可以让MongoDB单独完成所有操作,也可以让Nodejs完成。因为MongoDB不允许在其更新查询中执行数学运算,因此最好的方法是通过javascript本身(或者用于与MongoDB交互的任何内容)来实现这一点。只需将doc提取到orderSave(),获取此订单的endTime
,计算duration
并运行:
db.collection.update (
{'order' : {$eq: valueOfOrderToUpdate}},
{
$set : {'endTime': calculatedEndTimeValue},
$set : {'duration' : calculatedDuration}
},
{upsert : true}
);