findAndModifyコマンド

based on v25 (2010-10-26更新) - オリジナル

findして、modify (またはremove)

バージョン1.3.0以上

MongoDB 1.3以上で、"探して更新して、返す" というコマンドがサポートされています。このコマンドは、アトミックに ドキュメントを更新 し、取得することができます。デフォルトでは、このアップデートで更新されたものは返されるドキュメントには含まれないことに注意してください。

ドキュメントが返される必要がない場合には、 update を使ってください。これも同様に複数のドキュメントを更新することができます。

以下のような形になります。

db.runCommand( { findAndModify : <collection>,
                 <options> } )

MongoDBシェルには、findAndModify()というヘルパーメソッドがあります。いくつかのドライバにもヘルパーがあります。

少なくとも一つの update または remove パラメータが必要です。他の引数はオプションです。

引数 説明 デフォルト
query フィルターのためのクエリ {}
sort 複数のドキュメントがマッチした場合、このソート条件によってソートされた最初のオブジェクトが対象として選択されます {}
remove trueをセットすると、結果を返す前に削除します N/A
update 更新オブジェクト N/A
new trueをセットすると、更新後のオブジェクトを返します。 remove では無視されます false
fields フィールドの一部を取得 (バージョン1.5.0以上) All fields
upsert オブジェクトが存在しない作成します (1.5.4+) false

sort オプションは、キューのようなデータが保存されている場合に便利に使えます。例として、まだ処理されていない最大のプライオリティのジョブを自動的に取得する処理を示します。

> db.jobs.save( {
    name: "Next promo",
    inprogress: false, priority:0,
    tasks : [ "select product", "add inventory", "do placement"]
} );

> db.jobs.save( {
    name: "Biz report",
    inprogress: false, priority:1,
    tasks : [ "run sales report", "email report" ]
} );

> db.jobs.save( {
    name: "Biz report",
    inprogress: false, priority:2,
    tasks : [ "run marketing report", "email report" ]
} );
> job = db.jobs.findAndModify({
    query: {inprogress: false, name: "Biz report"},
    sort : {priority:-1},
    update: {$set: {inprogress: true, started: new Date()}},
    new: true
});

{
    "_id" : ...,
    "inprogress" : true,
    "name" : "Biz report",
    "priority" : 2,
    "started" : "Mon Oct 25 2010 11:15:07 GMT-0700 (PDT)",
    "tasks" : [
        "run marketing report",
        "email report"
    ]
}

arrayから要素を一つ取得し、アップデートという処理をアトミックに行えます。

> task = db.jobs.findAndModify({
    query: {inprogress: false, name: "Next promo"},
    update : {$pop : { tasks:-1}}, fields: {tasks:1},
    new: false } )
{
    "_id" : ...,
    "tasks" : [
        "select product",
        "add inventory",
        "do placement"
    ]
}

> db.jobs.find( { name : "Next promo"} )
{
    "_id" : ...,
    "inprogress" : false,
    "name" : "Next promo",
    "priority" : 0,
    "tasks" : [ "add inventory", "do placement" ]
}

または、単純に返されたオブジェクトを削除することもできます。

> job = db.jobs.findAndModify( {sort:{priority:-1}, remove:true} );
{
    "_id" : ...,
    "inprogress" : true,
    "name" : "Biz report",
    "priority" : 2,
    "started" : "Mon Oct 25 2010 10:44:15 GMT-0700 (PDT)",
    "tasks" : [
        "run marketing report",
        "email report"
    ]
}

> db.jobs.find()
{
    "_id" : ...,
    "inprogress" : false,
    "name" : "Next promo",
    "priority" : 0,
    "tasks" : [ "add inventory", "do placement" ]
}
{
    "_id" : ...,
    "name" : "Biz report",
    "inprogress" : false,
    "priority" : 1,
    "tasks" : [ "run sales report", "email report" ]
}

もし、クライアントがそのjobまたはたtaskを処理する前にクラッシュしてしまった場合、そのデータは永遠に失われます。

tests にたくさんのサンプルがあります。

ドライバにヘルパーファンクションがまだない場合、次のコマンドを直接実行してください。

job = db.runCommand({ findAndModify : "jobs",
sort : { priority : -1 },
remove : true
}).value;

shard での制限

findandmodify は、コレクションがshardされていない場合に限り mongos を通して同じように動きます。コレクションがshardされている場合、クエリはshardキーを含みます。これは、通常のshardでのアップデートと同じです。

See Also


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

blog comments powered by Disqus