0

我將出生日期(dob)存儲在用戶模型中,我想檢查它是否是今天的用戶生日。我該如何做查詢?貓鼬生日查詢

我已經開始嘗試,但顯然沒有

// User Model 
var UserSchema = new Schema({ 
     name: String, 
     email: { type: String, lowercase: true }, 
     role: { 
     type: String, 
     default: 'user' 
     }, 
     hashedPassword: String, 
     dob: { type: Date, default: new Date() }, 
     joinedOn: { type: Date, default: new Date() }, 
     leftOn: { type: Date }, 
     position: { type: String }, 
     provider: String, 
     salt: String, 
     google: {}, 
     github: {} 
    }); 

// Birtdhays 
exports.birthdays = function(req, res, next) { 
    var todayStart = moment().startOf('day'); 
    var todayEnd = moment().endOf('day'); 

    User 
    .find() 
    .where('dob').gt(todayStart).lt(todayEnd) 
    .limit(3) 
    .sort('dob') 
    .select('name dob') 
    .exec(function(err, users){ 
    if(err) return res.send(500, err); 
    res.json(200, users); 
    }); 
}; 
+0

添加了用戶模型 – Tino

回答

1

。假定你有存儲爲日期對象在文檔中,然後他們可能是這個樣子生日:

{ 
    "name": "Neil", 
    "dob": ISODate("1971-09-22T00:00:00Z") 
} 

所以這不僅僅是「一天」,而是全年以及最初選擇的出生日期。這可能看起來像是存儲出生日期的合乎邏輯的方式,並且對於許多目的而言它是有用的日期對象。但如何查詢呢?從當年得出的任何日期都不會與某一範圍內的該值相匹配,並且同一天的其他用戶數據可能在不同年份出現。

爲了解決這個問題,您可以執行一些JavaScript日期操作,並且還可以在聚合框架中使用MongoDB的某些功能(或者在mapReduce中使用JavaScript),以便從有用日期獲取數據進行匹配。

首先,你可以看看$dayOfyear運營商和代碼來獲取從當前日期作爲搭配使用:

var now = new Date(); 
var start = new Date(now.getFullYear() + "-01-01"); 
var diff = now - start; 
var oneDay = 1000 * 60 * 60 * 24; 
var dayOfYear = Math.floor(diff/oneDay);  


User.aggregate(
    [ 
     { "$project": { 
      "name": 1, 
      "dob": 1, 
      "dayOfYear": { "$dayOfYear": "$dob" } 
     }}, 
     { "$match": { "dayOfYear": dayOfYear } 
    ], 
    function(err,users) { 
     // work here 
    } 
) 

現在,一切都很好,或者看起來。但當然,閏年會發生什麼? 2月28日之後的所有日子都前進一天。你可以用其他方式解決這個問題,但如何只用「天」和「月」做對,而不是比賽:

var now = new Date(); 
var day = now.getDate();  // funny method name but that's what it is 
var month = now.getMonth() + 1; // numbered 0-11 


User.aggregate(
    [ 
     { "$project": { 
      "name": 1, 
      "dob": 1, 
      "day": "$dayOfMonth", 
      "month": "$month" 
     }}, 
     { "$match": { 
      "day": day, 
      "month": month 
     }} 
    ], 
    function(err,users) { 
     // work here 
    } 
) 

和聚合運營商$dayOfMonth$month幫助那裏。

因此,這一切都更好,你現在可以查詢「生日」,但有些東西仍然不是很對。雖然查詢會起作用,但顯然不是很有效。因爲你在這裏做的是通過集合中的所有結果,並操縱現有的日期以提取部分來執行匹配。

理想情況下,您不希望這樣做,並且讓「查詢」本身以簡單的筆畫爲目標以避免執行此操作來獲得匹配。這是建模進來,並在那裏你應該考慮增加更多的數據到您的文檔,其中類似下面的查詢比較常見:

{ 
    "name": "Neil", 
    "dob": ISODate("1971-09-22T00:00:00Z"), 
    "day": 22, 
    "month": 9 
} 

然後可以很容易地在這個查詢既是「天」和「月」字段可以也被索引以進一步提高性能並避免掃描整個集合的匹配:

var now = new Date(); 
var day = now.getDate();  // funny method name but that's what it is 
var month = now.getMonth() + 1; // numbered 0-11 

User.find({ "day": day, "month": month },function(err,users) { 
    // work here 
}) 

所以這些都是考慮因素。要麼接受使用聚合框架(或者可能是mapReduce)的操作,要麼將經常使用這樣的查詢和/或在集合中有許多項目,然後將其他字段添加到可以用作數據點的文檔模式中直接在查詢本身。

+0

感謝您長時間和令人印象深刻的答案! – Tino

0

我解決它以下列方式:

添加字段生日,brithmonth用戶模型,並增加了預保存掛鉤,使他們更新的任何更改生日:

UserSchema 
    .pre('save', function(next) { 

    this.birthmonth = this.dob.getMonth() + 1; 
    this.birthday = this.dob.getDate() 

     next(); 
    }); 

感謝Neil的靈感!