2

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

{
    "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""allAre""is"

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

4

1 回答 1

1

MongoDB 无法通过 1 个查询来满足您的要求。但是您可以通过两步查询来完成。

首先,将新值压入数组:

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

}
);

然后仅当小于最后一次推送时才更新“lastDate”。

  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”内部肯定有“最高日期推送”。

与您要求的第二个问题相关,您可以遵循类似的策略。仅{"allAre": false}{"_id":yourID, "items.is":false)}. 基本上只有当某个孩子的值为“假”时才设置“假”。如果您没有找到具有此属性的文档,则不要更新任何内容。

// 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) {
   }
  ); 
于 2016-10-17T11:14:38.020 回答