自动计算MongoDB中的字段 [英] Auto calculating fields in mongodb

查看:149
本文介绍了自动计算MongoDB中的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设MongoDB中有一些文档,看起来像这样:

Let's say there are documents in MongoDB, that look something like this:

{
    "lastDate" : ISODate("2013-14-01T16:38:16.163Z"),
    "items":[
        {"date":ISODate("2013-10-01T16:38:16.163Z")},
        {"date":ISODate("2013-11-01T16:38:16.163Z")},
        {"date":ISODate("2013-12-01T16:38:16.163Z")},
        {"date":ISODate("2013-13-01T16:38:16.163Z")},
        {"date":ISODate("2013-14-01T16:38:16.163Z")}        
    ]
}

甚至是这样:

{
    "allAre" : false,
    "items":[
        {"is":true},
        {"is":true},
        {"is":true},
        {"is":false},
        {"is":true}        
    ]
}

每次更改数组中的数据时,都应重新计算顶级字段"lastDate""allAre". "lastDate"应该是最大的"date".仅当所有项目的"is"为true时,"allAre"才应等于true.

The top level fields "lastDate" and "allAre" should be recalculated every time the data in array changes. "lastDate" should be the biggest "date" of all. "allAre" should be equal to true only if all the items have "is" as true.

我应该如何构建查询以实现MongoDB的这种行为?
在插入请求时预先计算一些值,而不是在get请求期间计算它们,是否被认为是一种好习惯?

How should I build my queries to achieve such a behavior with MongoDB?
Is it considered to be a good practice to precalculate some values on insert, instead of calculating them during the get request?

推荐答案

MongoDB无法通过1个查询来满足您的要求. 但是您可以通过两步查询来实现.

MongoDB cannot make what you are asking for with 1 query. But you can make it in two-step query.

首先,将新值推入数组:

First of all, push the new value into the array:

db.Test3.findOneAndUpdate(
{_id: ObjectId("58047d0cd63cf401292fe0ad")},
{$push: {"items":  {"date": ISODate("2013-01-27T16:38:16.163+0000")}}},
{returnNewDocument: true},
function (err, result) {

}
);

然后仅在小于上一个Pushed时更新"lastDate".

then update "lastDate" only if is less then the last Pushed.

  db.Test3.findOneAndUpdate (
   {_id: ObjectId("58047d0cd63cf401292fe0ad"), "lastDate":{$lt: ISODate("2013-01-25T16:38:16.163+0000")}},
   {$set: {"lastDate": ISODate("2013-01-25T16:38:16.163+0000")}},
   {returnNewDocument: true},
   function (err, result) {
   }
  ); 

需要第二个参数"lastDate",以避免出现竞争情况.这样,您可以确定在"lastDate"中肯定有推送的最高日期".

the second parameter "lastDate" is needed in order to avoid race condition. In this way you can be sure that inside "lastDate" there are for sure the "highest date pushed".

关于您要问的第二个问题,您可以遵循类似的策略.仅在{"_id":yourID, "items.is":false)}时更新{"allAre": false}.基本上,仅当的某个子项具有值"false"时才将其设置为"false".如果找不到具有此属性的文档,则不要进行任何更新.

Related to the second problem you are asking for you can follow a similar strategy. Update {"allAre": false} only if {"_id":yourID, "items.is":false)}. Basically set "false" only if some child of has a value 'false'. If you don't found a document with this property then do not update nothing.

// add a new Child to false
db.Test4.findOneAndUpdate(
{_id: ObjectId("5804813ed63cf401292fe0b0")},
{$push: {"items":  {"is": false}}},
{returnNewDocument: true},
 function (err, result) {

}
);

// update allAre to false if some child is false
db.Test4.findOneAndUpdate (
   {_id: ObjectId("5804813ed63cf401292fe0b0"), "items.is": false},
   {$set: {"allAre": false}},
   {returnNewDocument: true},
   function (err, result) {
   }
  ); 

这篇关于自动计算MongoDB中的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆