1

私はこれに似た文書を持っています:

{
     ...
     "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 +によってExpiresを更新したいです。MaxAgeは、ドキュメントごとに異なる場合があります。

つまり、1回のFindAndModify呼び出しで、ドキュメントの別のフィールドに依存しているときに、ドキュメントのフィールド(この場合はExpires)を更新する方法はありますか?

4

1 に答える 1

1

更新クエリ内でドキュメントの既存のフィールドを使用することはできません。ここにいくつかのオプションがあります。

存続時間コレクション:

有効期限が切れたときにドキュメントを削除する場合は、Time to Live コレクションを使用できます。Time to live コレクションでは、ドキュメントは指定された期間が経過すると自動的に削除されます。つまり、"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" }

ドキュメントを削除するプロセスは1 分間に 1 回しか実行されないことに注意してください。そのため、何かが削除される時間は、実際の有効期限の 1 分後になる場合があります。

2 つの検索と変更の呼び出し:

必要な値を含むドキュメントを挿入します。

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
}

デシベル.eval():

db.eval() もここで使用できますが、パフォーマンス上の理由から避ける必要があります

于 2012-09-23T19:17:34.827 に答える