2016-09-16 2 views
0

コレクションのサブアレイでフィールドを集計しようとしていますが、毎月行っています。私はMongo 2.6でこの作業を行っていましたが、最近3.0.12にアップグレードするとクエリにいくつかの誤った結果が生じます。合計がいくつかのクエリに対してリセットされていないようです。MongoDBコレクションで数ヶ月のデータを別々に集計する方法

現在のところ、私は非同期で12個のクエリを実行しており、それらのすべてが完了するのを待っています。これも2.6で動いていました。私のテーブルの構造は、このようなものです:

{ 
"_id" : ObjectId("<id>"), 
"userId" : ObjectId("<id>"), 
"accountId" : "1234567890", 
"transactionId" : "22222222333", 
"date" : ISODate("2016-09-08T04:00:00.000Z"), 
"description" : "SUPERCOOL STORE", 
"amount" : -123.45, 
"allocations" : [ 
    { 
     "jarId" : ObjectId("566faf1937af9ae11ef84bc4"), 
     "amount" : -100 
    }, 
    { 
     "jarId" : ObjectId("566faf1937af9ae11ef84bc1"), 
     "amount" : -23.45 
    } 
], 
"reconciled" : true, 
"tally" : true, 
"split" : true 
} 

そして、これは私のコードです:

var getTransactionAggregate = function (userId, month) { 
    var deferred = q.defer(); 
    var nextMonth = moment(month).add(1, 'M'); 

    Transactions.aggregate([ 
    {$match: { 
     userId: userId, 
     tally: true, 
     date: { 
     $gte: month.toDate(), 
     $lt: nextMonth.toDate() 
     } 
    }}, 
    {$project: { _id: 0, allocations: 1 } }, 
    {$unwind: '$allocations'}, 
    {$group: {_id: '$allocations.jarId', total: {$sum: '$allocations.amount'}}} 
    ]).then(function(data) { 
    deferred.resolve(data); 
    }) 
    .catch(function (err) { 
    logger.error(err); 
    deferred.reject(err); 
    }); 

    return deferred.promise; 
}; 

summaryReport = function (req, res) { 
    Jars.aggregate([ 
    { $match: {userId: new ObjectID(req.user._id)} }, 
    { $sort: {name: 1} } 
    ]) 
    .then(function (jars) { 
    var month = moment(moment().format('YYYY-MM') + '-01T00:00:00.000'); 
    var i, j; 
    var promises = []; 

    for (i = 0; i < 12; i++) { 
     promises.push(getTransactionAggregate(new ObjectID(req.user._id), month)); 
     month.add(-1, 'M'); 
    } 

    q.allSettled(promises).then(function (data) { 
     for (i = 0; i < data.length; i++) { 
     // data[i].value here is returned incorrectly from the queries 

     ........ 
    }); 
    }); 
}; 

だから、基本的に何が起こっているのかは、最初の月は、正しいデータが含まれているが、合計がデータを含めるように続けていることを思わ前のすべての月から。クエリを分解すると、日付範囲で正しいトランザクションが返され、アンワインドも機能します。グループのステップが犯人のように見えるときだけ。 Mongoを3.0.12にアップグレードする前に、同じロジックが正常に機能しました。

このクエリをワンショットで実行するより良い方法があるのでしょうか、または12回のクエリを最善の方法で実行していますか?

答えて

0

それが原因で上記の回答で述べた$とケースではないものの、一致に関連していることになりました。それは、日付の一致と関係していた、私はあなたが同じだと思ったが、新しいDate()を使用するときと同じ日付オブジェクトを返さない瞬間object.toDate()を推測している。正しい方向に私を指しているためDate query with ISODate in mongodb doesn't seem to workと@Leifに

Transactions.aggregate([ 
    {$match: { 
    userId: userId, 
    tally: true, 
    $and: [ 
     { date: { $gt : new Date(month.toISOString()) } }, 
     { date: { $lt: new Date(nextMonth.toISOString()) } } 
    ] 
    }}, 
    {$unwind: '$allocations'}, 
    {$group: {_id: '$allocations.jarId', total: {$sum: '$allocations.amount'}}} 
]) 

クレジット:

とにかく作業ロジックは次のようになります。

1

$matchフェーズで問題があるようです。あなたのdateフィールドは、2つの式があり、このシナリオあなたはdocsに指定されている、$and演算子を使用する必要があります。

のMongoDB式のコンマ 区切りリストを指定する場合は、暗黙のAND演算を提供します。同じフィールドまたは演算子が複数の式で指定された である必要がある場合は、$と 演算子との明示的ANDを使用する必要があります。

だから、次のようになります。

{$match: { 
    userId: userId, 
    tally: true, 
    $and: [ 
     { date: { $gte : month.toDate() } }, 
     { date: { $lt: nextMonth.toDate() } } 
    ] 
}} 
+0

お返事ありがとうございます!あなたはそれがマッチと何かを持っている必要があります、私は最初の原則に戻ってロジックを持って来て、1ヶ月と3ヶ月合計、1ヶ月のクエリは3つのアイテムを返します。先月は正しく一致した1つのアイテムを返します。 しかし、マッチロジックを変更することは、提案したようには役に立たなかったようです。どちらも私のすべての基準を$と。 – Eric

関連する問題