2014-12-13 19 views
1

我发现通过MongoDB的我的方式,并有一个包含这种形状的一些文件集合的标准:检索多个(转化)值在MongoDB中组匹配从组本身

{ 
"_id" : ObjectId("547a13b70dc5d228db81c475"), 
"INSTRUMENT" : "InstrumentA", 
"BID" : 5287, 
"ASK" : 5290, 
"TIMESTAMP" : ISODate("2014-10-01T23:57:27.137Z") 
} 
{ 
"_id" : ObjectId("547a0da20dc5d228db2f034d"), 
"INSTRUMENT" : "InstrumentB", 
"BID" : 0.88078, 
"ASK" : 0.88098, 
"TIMESTAMP" : ISODate("2014-10-01T23:58:59.637Z") 
} 

什么我期待得到是最后一个已知的中间(BID + ASK)/2之前给定的ISODate每个INSTRUMENT。我得到了最后一个仪器信息的时间和最后一个仪器的最后一个值。尽管以下看起来像是有效的,但lastOccurance正在被仪器污染。

db.runCommand(
    { 
    group: 
     { 
     ns: 'collectionTest', 
     key : { INSTRUMENT : 1} , 
     cond: { TIMESTAMP: { $lte: ISODate("2014-10-01 08:30:00") } } , 
     $reduce: function(curr, result) { 
         if(curr.TIMESTAMP > result.lastOccurance) 
         { 
         result.lastOccurance = curr.TIMESTAMP; 
         result.MID = (curr.BID + curr.ASK)/2; 
         result.INSTRUMENT = curr.INSTRUMENT; 
         }else 
         { 
         result.lastOccurance = null; 
         result.MID = null; 
         result.INSTRUMENT = null; 
         } 
        }, 
     initial: { lastOccurance : ISODate("1900-01-01 00:00:00") } 
     } 
    } 
) 

如果有人能看到此代码的修复程序,请让我知道。

回答

1

尽可能使用aggregate而不是group,因为它提供了更好的性能并支持分片。

随着aggregate,你可以这样做,因为:

db.test.aggregate([ 
    // Only include the docs prior to the given date 
    {$match: {TIMESTAMP: { $lte: ISODate("2014-10-01 08:30:00") }}}, 
    // Sort them in descending TIMESTAMP order 
    {$sort: {TIMESTAMP: -1}}, 
    // Group them by INSTRUMENT, taking the first one in each group (which will be 
    // the last one before the given date) and computing the MID value for it. 
    {$group: { 
     _id: '$INSTRUMENT', 
     MID: {$first: {$divide: [{$add: ['$BID', '$ASK']}, 2]}}, 
     lastOccurance : {$first: '$TIMESTAMP'} 
    }} 
]) 
+0

谢谢你的提示! – 2014-12-14 04:01:18