![](/img/trans.png)
[英]How to find a document in mongoose and return the last 10 days from array of objects?
[英]Find last document of the day for the last 7 days
我每小時都會在架構中添加條目,以便跟蹤幾天內的增長情況,同時保持當前一天的當前得分。 現在,我希望能夠獲取過去一周每天的最新記錄。 結果將是前6天午夜或前后的6條記錄,而第7條是當天的最新記錄。
這是我的架構:
var schema = new Schema({
aid: { type: Number }
, name: { type: String }
, score: { type: Number }
, createdAt: { type: Date, default: Date.now() }
})
編輯
我試過使用此靜態,但它提取相同的記錄7次
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
for (var i = 1; i <= 7; i++) {
this.where('name', new RegExp(name, 'i'))
.where('createdAt')
.gte(now - (i * oneday))
.desc('createdAt')
.findOne(function(err,doc){
docs.push(doc)
})
}
}
如果我使用的是SQL,我將選擇MAXDATE進行子查詢,並將其加入我的主查詢中,以檢索所需的結果。 無論如何要在這里做?
克里斯蒂娜(Kristina Chodorow)在她的《 MongoDB:權威指南 》( MongoDB:The Definitive Guide)一書中詳細介紹了該任務的詳細配方 :
假設我們有一個跟蹤股價的站點。 從上午10點到下午4點每隔幾分鍾,它將獲取最新的股票價格,並將其存儲在MongoDB中。 現在,作為報表應用程序的一部分,我們希望找到過去30天的收盤價。 使用組可以很容易地做到這一點。
我對貓鼬不熟悉,但是我嘗試將她的示例調整為適合您的以下情況。 注意,我將createdAt
default
屬性從一個值更改為一個函數,並向您的模式添加了一個額外的字段datestamp
:
var oneday = 24 * 60 * 60;
var schema = new Schema({
aid: { type: Number }
, name: { type: String }
, score: { type: Number }
// default: is a function and called every time; not a one-time value!
, createdAt: { type: Date, default: Date.now }
// For grouping by day; documents created on same day should have same value
, datestamp: { type: Number
, default: function () { return Math.floor(Date.now() / oneday); }
}
});
schema.statics.getLastWeek = function(name, fn) {
var oneweekago = Date.now() - (7 * oneday);
ret = this.collection.group({
// Group by this key. One document per unique datestamp is returned.
key: "datestamp"
// Seed document for each group in result array.
, initial: { "createdAt": 0 }
// Update seed document if more recent document found.
, reduce: function(doc, prev) {
if (doc.createdAt > prev.createdAt) {
prev.createdAt = doc.createdAt;
prev.score = doc.score;
// Add other fields, if desired:
prev.name = doc.name;
}
// Process only documents created within past seven days
, condition: { "createdAt" : {"$gt": oneweekago} }
}});
return ret.retval;
// Note ret, the result of group() has other useful fields like:
// total "count" of documents,
// number of unique "keys",
// and "ok" is false if a problem occurred during group()
);
一種解決方案是使用group()按天對記錄進行分組。 它花哨,緩慢且可能會阻塞(意味着其他任何東西都無法同時運行),但是如果您的記錄集不是太大,那么它就非常強大。
組: http : //www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group
至於貓鼬,我不確定它是否直接支持group(),但是您可以通過執行以下操作(主要是偽代碼)來使用node-mongodb-native實現:
schema.statics.getLastWeek = function(name, cb) {
var keys = {} // can't remember what this is for
var condition = {} // maybe restrict to last 7 days
var initial = {day1:[],day2:[],day3:[],day4:[],day5:[],day6:[],day7:[]}
var reduce = function(obj, prev) {
// prev is basically the same as initial (except with whatever is added)
var day = obj.date.slice(0,-10) // figure out day, however it works
prev["day" + day].push(obj) // create grouped arrays
// you could also do something here to sort by _id
// which is probably also going to get you the latest for that day
// and use it to replace the last item in the prev["day" + 1] array if
// it's > that the previous _id, which could simplify things later
}
this.collection.group(keys, condition, initial, reduce, function(err, results) {
// console.log(results)
var days = results // it may be a property, can't remember
var lastDays = {}
days.forEach(function(day) {
// sort each day array and grab last element
lastDays[day] = days[day].sort(function(a, b) {
return a.date - b.date // check sort syntax, you may need a diff sort function if it's a string
}).slice(-1) // i think that will give you the last one
})
cb(lastDays) // your stuff
})
}
群組和地圖之間的其他一些比較從我的博客中減少了: http : //j-query.blogspot.com/2011/06/mongodb-performance-group-vs-find-vs.html
本機驅動程序中沒有有關group命令的文檔,因此您必須在此處瀏覽源代碼: https : //github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/ collection.js
同樣要進行排序,請檢查https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort以獲取確切的語法
編輯:更好的主意!
只需有一個名為“ lastRequestOfDay”的特殊集合,並將_id設置為當天即可。 用每個新請求覆蓋值。 這將是超級容易查詢和快速編寫的方法,並且總是每天都有最后寫入的值!
將另一個屬性添加到名為dateAdded
的架構中。
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
for (var i = 0; i < 7; i++) {
this.where('name', new RegExp(name, 'i'))
.where('createdAt')
.lt(now - (i * oneday))
.gte(now - ((i + 1) * oneday))
.desc('createdAt')
.findOne(function(err,doc){
// might not always find one
docs.push(doc)
})
}
return fn(null, docs)
}
嘗試這樣的事情:
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
, that = this
function getDay(day){
that.where('name', new RegExp(name, 'i'))
.where('createdAt')
.gte(now - (day * oneday))
.desc('createdAt')
.findOne(function(err,doc){
docs.push(doc)
})
}
for (var i = 1; i <= 7; i++) {
getDay(i);
}
}
似乎沒人試圖“接近午夜”。 :)我在原始代碼中看到的問題是它檢查的時間大於或等於x天前……這將始終返回最近的時間。 我對為什么DeaDEnD的解決方案會返回7次相同的記錄感到困惑。 另外,您從未致電過fn
,但這並不是您最擔心的問題,不是嗎?
嘗試添加.lt(now - (now % oneday) - (i - 1) * oneday)
(假設0索引;如果是1索引,則改成i - 2
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.