2016-08-02 100 views
1

目前,我想要查詢的集合爲每個$文件數量,讓我們稱之爲Telemetry,通過陣列上匹配的文檔:返回X的匹配查詢

var hardwareIDs = ['A','B','C']; 
Telemetry.find({ hardwareID: { $in: hardwareIDs }}); 

下面是一個Telemetry記錄的例子可能看起來像:

{ 
    _id: xxxx, 
    insertedAtUTC: xxxx, 
    hardwareID: xxxx, 
    year: 2016, 
    month: 2, 
    day: 31, 
    hour: 0, 
    data: [] 
} 

但是我發現很難做的就是,讓我們說,每個匹配查詢最新的3個文件。所以有效地,我想返回一個類似於這樣的遊標:

[ 
    { insertedAtUTC: 3, hardwareID: "A", ... }, 
    { insertedAtUTC: 2, hardwareID: "A", ... }, 
    { insertedAtUTC: 1, hardwareID: "A", ... }, 
    { insertedAtUTC: 3, hardwareID: "B", ... }, 
    { insertedAtUTC: 2, hardwareID: "B", ... }, 
    { insertedAtUTC: 1, hardwareID: "B", ... }, 
    { insertedAtUTC: 3, hardwareID: "C", ... }, 
    { insertedAtUTC: 2, hardwareID: "C", ... }, 
    { insertedAtUTC: 1, hardwareID: "C", ... } 
] 

有關如何制定一個MongoDB查詢來解決這個問題的任何想法?

我用meteor標記了這個標記,因爲我在MeteorJS中使用了MongoDB。我目前正在嘗試發佈輕量級光標,因爲Telemetry集合相當大,但我認爲這不會對解決方案產生任何影響。

回答

1

您可以通過使用mapreduce來實現:發出所有hardwareID,而不是reduce,通過insertedAtUTC對它們進行排序。此外,如果您想過濾字段的投影更多,您可以應用聚合,展開和爲您的文檔做一個投影。 看看我的例子的script.js:

use stackoverflow 

db.dropDatabase() 

db.telemetry.insert(
    [ 
     { hardwareID: "C", insertedAtUTC: 2 }, 
     { hardwareID: "C", insertedAtUTC: 3 }, 
     { hardwareID: "C", insertedAtUTC: 1 }, 
     { hardwareID: "A", insertedAtUTC: 1 }, 
     { hardwareID: "A", insertedAtUTC: 2 }, 
     { hardwareID: "A", insertedAtUTC: 3 }, 
     { hardwareID: "B", insertedAtUTC: 3 }, 
     { hardwareID: "B", insertedAtUTC: 2 }, 
     { hardwareID: "B", insertedAtUTC: 1 }, 
     { hardwareID: "X", insertedAtUTC: 2 }, 
     { hardwareID: "X", insertedAtUTC: 1 } 
    ] 
) 


var hardwareIDs = ['A','B','C']; 

var map = function map(){ 
    emit(this.hardwareID, this); 

}; 

var reduce = function(key, values){ 
    var sorted_values = values.sort(function(first, second) { 
     return second.insertedAtUTC - first.insertedAtUTC; 
    }).slice(0,2); 
    return {key, sorted_values}; 
}; 


db.runCommand({"mapReduce":"telemetry", map:map, reduce:reduce, out:{replace:"telemetry2"}, query:{ hardwareID: { $in: hardwareIDs }}}) 

var result = db.telemetry2.aggregate(
    [ 
    { $unwind : {path: '$value.sorted_values' }}, 
    { $project: { 
     _id: '$value.sorted_values._id', 
     hardwareID: '$value.sorted_values.hardwareID', 
     insertedAtUTC: '$value.sorted_values.insertedAtUTC' 
     } 
    } 
    ] 
); 

while(result.hasNext()){ 
    printjson(result.next()); 
} 

您可以通過

mongo < script.js 
+0

運行控制檯腳本標記此爲答案,因爲這肯定回答了這個問題,但使用的MapReduce在不幸的是,輸出Meteor框架返回了一些意想不到的結果。如果有必要,將更多地排除故障併發布另一個問題。謝謝你的時間! – jkhedani

相關問題