2016-08-02 102 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

相关问题