我通过Meteor使用MiniMongo,我正在尝试根据动态查询集创建频率表。
我有两个主要字段localHour
和localDay
。我期待很多重叠,我想确定最重叠的位置。我目前的做法是这样的。
if(TempStats.findOne({
localHour: hours,
localDay: day
})){//checks if there is already some entry on the same day/hour
TempStats.update({//if so, we just increment frequency
localHour: hours,
localDay: day
},{
$inc: {freq: 1}
})
} else {//if nothing exists yet, we put in a new entry
TempStats.insert({
localHour: hours,
localDay: day,
freq: 1
});
}
基本上,每次我想要插入新数据时,此代码都会运行。它现在工作正常,因为,在插入所有数据后,我可以按频率排序以查找小时数和小时数。天最常出现(TempStats.find({}, {sort: {freq: -1}}).fetch()
)。
但是,我正在寻找一种通过频率搜索任何键的方法。例如,搜索 day 哪一切最常发生,而不是日期和小时。按照我目前的方式,我需要有多个数据库和不同的插入方法,这有点荒谬。是否有Mongo(特别是MiniMongo)解决方案来基于密钥进行频率映射?
谢谢!
答案 0 :(得分:3)
看起来miniMongo实际上并不支持聚合,这使得这种操作很难。一种方法是在每天结束时聚合自己并将该聚合记录插入到您的数据库中(不使用小时字段或将其设置为-1)。相反,浪费时你也可以在每次插入时更新该记录。这将允许您为两者使用相同的集合,并且在其他dbs中相当常见。
此外,您应该考虑@ nickmilon的第一个建议,因为使用带有$ inc运算符的upsert语句会将您的示例缩减为每个数据点的单个操作。
答案 1 :(得分:2)
答案 2 :(得分:1)
这基本上是一个简单的map-reduce问题。
首先,不要将派生数据分成2个字段。这违反了DB最佳实践。如果数据以这种方式发送给您,请使用它来创建Date
对象。我假设您有一堆正在订阅的集合,然后将所有这些集合聚合到此临时本地集合中。这是map-reduce模式的映射。此时,由于您的查询未知,因此会浪费CPU(即使它是您的客户端)进行聚合。先映射,减少秒。你应该拥有的是一个充满日期时间的集合。如果您愿意,请将其称为TempMapCollection
。现在,使用forEach()
并传入reduce函数(按天,按小时等)。
您可以缩小为另一个本地集合,或者转换为javascript对象。我喜欢使用集合,但如果对象很复杂,那么你就会在那里得到EJSON错误。由于您的对象只不过是日期时间,因此请使用集合。
所以你有类似的东西:
TempMapCollection.find().forEach(function(doc) {
var date = doc.dateTime.getDate();
TempReduceCollection.upsert({timequery: hours}, {$inc: {freq: 1}});
})
现在查询您的reduce集合。如果您想要执行2个唯一查询,则还有一个额外的好处,即您不必重新映射。