让我们说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"
才应等于true。
如何构建查询以使用MongoDB实现此类行为? 是否认为在插入时预先计算某些值是一种好习惯,而不是在获取请求期间计算它们?
答案 0 :(得分: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)}
。基本上设置" 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) {
}
);