24

私は多くの同様の構造化文書を含むコレクションを持っています.2つの文書は次のようになります

入力:

{ 
    "_id": ObjectId("525c22348771ebd7b179add8"), 
    "cust_id": "A1234", 
    "score": 500, 
    "status": "A"
    "clear": "No"
}

{ 
    "_id": ObjectId("525c22348771ebd7b179add9"), 
    "cust_id": "A1234", 
    "score": 1600, 
    "status": "B"
    "clear": "No"
}

デフォルトではclear、すべてのドキュメントは"No"

cust_idReq: およびに属している場合、同じ のすべてのドキュメントのスコアを追加する必要がstatus "A"ありstatus "B"ます。scoreを超える場合は、すべてのドキュメントの属性を同じ2000に更新する必要があります。clear"Yes"cust_id

期待される出力:

{ 
    "_id": ObjectId("525c22348771ebd7b179add8"), 
    "cust_id": "A1234", 
    "score": 500, 
    "status": "A"
    "clear": "Yes"
}

{
    "_id": ObjectId("525c22348771ebd7b179add9"), 
    "cust_id": "A1234", 
    "score": 1600, 
    "status": "B"
    "clear": "Yes"
}

はい、1600+500 = 2100 であり、2100 > 2000 であるためです。


私のアプローチ:集計関数で合計を取得することしかできませんでしたが、更新に失敗しました

db.aggregation.aggregate([
    {$match: {
        $or: [
            {status: 'A'},
            {status: 'B'}
        ]
    }},
    {$group: {
        _id: '$cust_id',
        total: {$sum: '$score'}
    }},
    {$match: {
        total: {$gt: 2000}
    }}
])

どうすればよいか教えてください。

4

5 に答える 5

16

多くのトラブルの後、モンゴシェルを実験して、ようやく私の質問に対する解決策が得られました。

擬似コード:

# To get the list of customer whose score is greater than 2000
cust_to_clear=db.col.aggregate(
    {$match:{$or:[{status:'A'},{status:'B'}]}},
    {$group:{_id:'$cust_id',total:{$sum:'$score'}}},
    {$match:{total:{$gt:500}}})

# To loop through the result fetched from above code and update the clear
cust_to_clear.result.forEach
(
   function(x)
   { 
     db.col.update({cust_id:x._id},{$set:{clear:'Yes'}},{multi:true}); 
   }
)

同じ質問に対して別の解決策がある場合は、コメントしてください。

于 2013-10-20T11:21:34.217 に答える
6

これは、次の 2 つの手順で行う必要があります。

  1. cust_id合計スコアが 200 を超える顧客 ( ) を特定する
  2. これらの顧客ごとにclearYes

最初の部分については、すでに適切な解決策があります。2 番目の部分は、データベースへの個別のupdate()呼び出しとして実装する必要があります。

擬似コード:

# Get list of customers using the aggregation framework
cust_to_clear = db.col.aggregate(
    {$match:{$or:[{status:'A'},{status:'B'}]}},
    {$group:{_id:'$cust_id', total:{$sum:'$score'}}},
    {$match:{total:{$gt:2000}}}
    )

# Loop over customers and update "clear" to "yes"
for customer in cust_to_clear:
    id = customer[_id]
    db.col.update(
        {"_id": id},
        {"$set": {"clear": "Yes"}}
    )

すべての顧客に対してデータベース呼び出しを行う必要があるため、これは理想的ではありません。この種の操作を頻繁に行う必要がある場合は、スキーマを修正して、各ドキュメントに合計スコアを含めることができます。(これはアプリケーションで維持する必要があります。) この場合、単一のコマンドで更新を実行できます。

db.col.update(
    {"total_score": {"$gt": 2000}},
    {"$set": {"clear": "Yes"}},
    {"multi": true}
    )
于 2013-10-15T20:26:50.617 に答える
3

MongoDB 2.6.では、同じコマンドで集計クエリの出力を書き込めるようになります。

詳細はこちら: http://docs.mongodb.org/master/reference/operator/aggregation/out/

于 2013-10-20T12:18:31.320 に答える