2015-02-08 44 views
0

部分周的數據分組,我有一些文檔(每日開盤價爲股票),如如下:如何處理的mongodb

/* 0 */ 
{ 
    "_id" : ObjectId("54d65597daf0910dfa8169b0"), 
    "D" : ISODate("2014-12-29T00:00:00.000Z"), 
    "O" : 104.98 
} 

/* 1 */ 
{ 
    "_id" : ObjectId("54d65597daf0910dfa8169af"), 
    "D" : ISODate("2014-12-30T00:00:00.000Z"), 
    "O" : 104.73 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("54d65597daf0910dfa8169ae"), 
    "D" : ISODate("2014-12-31T00:00:00.000Z"), 
    "O" : 104.51 
} 

/* 3 */ 
{ 
    "_id" : ObjectId("54d65597daf0910dfa8169ad"), 
    "D" : ISODate("2015-01-02T00:00:00.000Z"), 
    "O" : 103.75 
} 

/* 4 */ 
{ 
    "_id" : ObjectId("54d65597daf0910dfa8169ac"), 
    "D" : ISODate("2015-01-05T00:00:00.000Z"), 
    "O" : 102.5 
} 

,我想通過每週彙總記錄,所以我可以每週平均開盤價。我第一次嘗試是使用:

db.ohlc.aggregate({ 
    $match: { 
     D: { 
      $gte: new ISODate('2014-12-28') 
     } 
    } 
}, { 
    $project: { 
     year: { 
      $year: '$D' 
     }, 
     week: { 
      $week: '$D' 
     }, 
     O: 1 
    } 

}, { 
    $group: { 
     _id: { 
      year: '$year', 
      week: '$week' 
     }, 
     O: { 
      $avg: '$O' 
     } 
    } 
}, { 
    $sort: { 
     _id: 1 
    } 
}) 

卜我很快意識到的結果是不正確的,上週這兩個2014年(週數52)和2015年第一週(週數0)的部分周。通過這種彙總,我將獲得12/29-12/31/2014的平均價格,以及2015年2月1日(這是2015年第一週的唯一交易日期)的平均價格,但在我的申請中,我需要將2015年12月29日至2015年2月1日的數據進行分組。有什麼建議?

+1

我很好奇,爲什麼我的問題得到反對票?我很樂意找出原因。 – 2015-02-08 14:09:13

回答

0

從我的經驗來看,這不是解決問題的好方法。爲什麼?這絕對不會擴展,所需的計算量非常大,特別是要進行分組。

我會在你的情況下做的是將部分應用程序邏輯移至數據庫中的文檔。

我的第一種方法是添加一個「星期」字段,該字段將聲明樣本所屬日期的前一個(或下一個)星期日。這在插入時很容易做到。然後,您可以簡單地按該字段運行聚合方法分組。如果您想要獲得更多性能,請爲{ symbol : 1, week : 1 }添加一個索引並對其進行排序。

我的第二種方法是,如果您計劃進行大量這種類型的聚合,基本上會有以每週方式對樣本進行分組的文檔。像這樣:

{ 
    week : <Day Representing Week>, 
    prices: [ 
     { Day Sample }, ... 
    ] 
} 

然後,你可以直接在這些文件上工作。這將幫助您以顯着的方式減少索引,從而加快速度。

+0

通過添加預先計算的字段(星期),可以加快查詢的速度。然而,性能增益並不是非常顯着(純分組爲0.75s,預先計算的字段爲0.4s),但我仍然按照您的第一個建議並添加一個基於我的帖子中的方法計算的星期字段。在將數據導入數據庫時​​,使用awk(這比我不得不說的方式更容易)計算該值。我收藏的文件超過6,100萬份,複合索引{S:1,D:1}。我沒有使用你的第二個建議,因爲要分組的週數需要是動態的。 – 2015-02-10 03:25:45

1

我把這個用於candelization;allowDiskUsage,out和一些日期過濾器很好用。也許你可以採用分組?

db.getCollection('market').aggregate(
[ 
    { $match: { date: { $exists: true } } }, 
    { $sort: { date: 1 } }, 
    { $project: { _id: 0, date: 1, rate: 1, amount: 1, tm15: { $mod: [ "$date", 900 ] } } }, 
    { $project: { _id: 0, date: 1, rate: 1, amount: 1, candleDate: { $subtract: [ "$date", "$tm15" ] } } }, 
    { $group: { _id: "$candleDate", open: { $first: '$rate' }, low: { $min: '$rate' }, high: { $max: '$rate' }, close: { $last: '$rate' }, volume: { $sum: '$amount' }, trades: { $sum: 1 } } } 
]) 
+0

有什麼機會可以更好地解釋這個嗎?我試圖讓它在貿易數據上工作,想用5,10,15分鐘的蠟燭等組合,但沒有奏效。什麼$ date是.. Unix時間毫秒?你能顯示一些樣本輸入文件嗎?謝謝。 – 2017-06-16 02:46:33