我有一个类似的文件:
{
...
"LastAccess" : "2012-09-19T05:47:45.982Z", // Time of last document access
"Expires" : "2012-09-19T06:47:45.982Z", // Time this document expires
"MaxAge" : 3600, // Seconds to live
}
我认为实现我想要的唯一安全方法是FindAndModify,所以我的问题是,我想将 LastAccess 更新为当前UTC时间(这显然很容易),但随后我想通过 LastAccess + MaxAge 更新过期,其中MaxAge在文档到文档的基础上可能不同。
简而言之,在一个FindAndModify调用中,是否依赖于文档中的另一个字段来更新文档中的字段(在本例中为Expires)?
答案 0 :(得分:1)
您无法在更新查询中使用文档中的现有字段。这里有几个选项。
如果要在文档过期时删除文档,则可以使用生存时间集合。及时收集,文档会在指定的持续时间后自动删除,这意味着您可以完全删除“Expires”和“MaxAge”字段。
创建具有30秒生命周期的TTL索引:
mongos> db.last.ensureIndex({ "LastAccess" : 1 }, { "expireAfterSeconds" : 30 })
插入我们的文件:
mongos> db.last.insert({ "Value" : "No Expiration" })
mongos> db.last.insert({ "Value" : "Expiration", "LastAccess": new Date() })
mongos> db.last.find()
{ "_id" : ObjectId("505d15ac283b060dbc637ec0"), "Value" : "No Expiration" }
{ "_id" : ObjectId("505d15b1283b060dbc637ec1"), "Value" : "Expiration", "LastAccess" : ISODate("2012-09-22T01:34:41.102Z") }
睡眠15秒:
mongos> sleep(15000)
null
mongos> db.last.find()
{ "_id" : ObjectId("505d15ac283b060dbc637ec0"), "Value" : "No Expiration" }
{ "_id" : ObjectId("505d15b1283b060dbc637ec1"), "Value" : "Expiration", "LastAccess" : ISODate("2012-09-22T01:34:41.102Z") }
更新我们的访问时间:
mongos> db.last.update({ "Value" : "Expiration" }, { "$set" : { "LastAccess" : new Date() }})
mongos> sleep(15000)
null
这两份文件仍然存在:
mongos> db.last.find()
{ "_id" : ObjectId("505d15ac283b060dbc637ec0"), "Value" : "No Expiration" }
{ "LastAccess" : ISODate("2012-09-22T01:35:07.629Z"), "Value" : "Expiration", "_id" : ObjectId("505d15b1283b060dbc637ec1") }
睡眠30秒:
mongos> sleep(30000)
null
现在只有我们没有过期的文件在附近:
mongos> db.last.find()
{ "_id" : ObjectId("505d15ac283b060dbc637ec0"), "Value" : "No Expiration" }
请注意,删除文档的过程只会运行once per minute,因此删除某些内容的时间可能会在实际到期日期后的一分钟内停止。
插入包含所需值的文档:
mongos> db.last.insert({"Value":"oldvalue","LastAccess":new Date(),"Expires":new Date((new Date()).valueOf() + 3200),"MaxAge":3200,InProgress:false})
mongos> db.last.find()
{ "_id" : ObjectId("505b89292271f63498810600"), "Value" : "oldvalue", "LastAccess" : ISODate("2012-09-20T21:22:49.637Z"), "Expires" : ISODate("2012-09-20T21:22:52.837Z"), "MaxAge" : 3200, "InProgress" : false }
修改InProgress字段以警告其他人我们正在查看MaxAge 字段(如果你不在乎有人在你做的时候改变了MaxAge字段 这个,你不需要InProgress字段,你可以对此进行查找 步骤):
mongos> doc = db.last.findAndModify({ "query" : { "Value" : "oldvalue", "InProgress" : false }, "update" : { "$set" : { "InProgress" : true } } });
{
"_id" : ObjectId("505b89292271f63498810600"),
"Value" : "oldvalue",
"LastAccess" : ISODate("2012-09-20T21:22:49.637Z"),
"Expires" : ISODate("2012-09-20T21:22:52.837Z"),
"MaxAge" : 3200,
"InProgress" : false
}
mongos> db.last.find()
{ "_id" : ObjectId("505b89292271f63498810600"), "Value" : "oldvalue", "LastAccess" : ISODate("2012-09-20T21:22:49.637Z"), "Expires" : ISODate("2012-09-20T21:22:52.837Z"), "MaxAge" : 3200, "InProgress" : true }
实际使用新的截止日期更新文档,并将InProgress设置为false以标记我们不再查看MaxAge:
mongos> db.last.findAndModify({ "query" : { "Value" : "oldvalue", "InProgress" : true }, "update" : { "$set" : { "Value" : "newvalue", "LastAccess" : new Date(), "Expires" : new Date((new Date()).valueOf() + doc.MaxAge), "InProgress" : false } }, "new" : true });
{
"_id" : ObjectId("505b89292271f63498810600"),
"Value" : "newvalue",
"LastAccess" : ISODate("2012-09-20T21:23:29.058Z"),
"Expires" : ISODate("2012-09-20T21:23:32.258Z"),
"MaxAge" : 3200,
"InProgress" : false
}
db.eval()也可以在这里使用,但performance reasons
应该避免使用