最後に、this answerの回答があります。それはthe Aggregation Pipelineを使用します。
まず、Date
/ISODate
タイプを使用して、年/月/日フィールドの代わりに誕生日を保存することにしました。だから私のtest
コレクションは、これらのエントリを持っているでしょう:
{
"birthday" : ISODate("1985-04-16T10:00:00.000Z"),
"name" : "J"
}
{
"birthday" : ISODate("1985-09-16T11:00:00.000Z"),
"name" : "E"
}
{
"birthday" : ISODate("1950-11-11T11:00:00.000Z"),
"name" : "M"
}
{
"birthday" : ISODate("1947-05-06T10:00:00.000Z"),
"name" : "D"
}
その後、私はアグリゲーションパイプラインで使用するために、いくつかの構造を構築:pDayOfYear
で
- は誕生日と今日の年のシーケンシャル年を取得し、使用して$dayOfYear operator。
pLeapYear
減算1からdayofYear
フィールドの場合、birthday
はうるう年であり、各誕生日と今日の差を計算します。
pPast
には、誕生日に365を加えて、positiveDiff
フィールドがあります。 降順で
positiveDiff
フィールドによって
pSort
ソート結果で
- ので、私たちは
pFirst
では、次の誕生日
- のリストを持つことができることができる唯一の最初の結果を取得します。
クエリは次のようになります。だから私は、次の誕生日のIDになるだろうと私はIDによってフィールドを問い合わせることができ
pDayOfYear = {
"$project": {
"birthday": 1,
"todayDayOfYear": {"$dayOfYear": new ISODate()},
"leap": {"$or": [
{"$eq": [0, {"$mod": [{"$year": "$birthday"}, 400]}]},
{"$and": [
{"$eq": [0, {"$mod": [{"$year": "$birthday"}, 4]}]},
{"$ne": [0, {"$mod": [{"$year": "$birthday"}, 100]}]}
]}
]},
"dayOfYear": {"$dayOfYear": "$birthday"}
}
}
pLeapYear = {
"$project": {
"birthday": 1,
"todayDayOfYear": 1,
"dayOfYear": {
"$subtract": [
"$dayOfYear",
{
"$cond": [
{"$and":
["$leap",
{"$gt": ["$dayOfYear", 59]}
]},
1,
0]
}
]},
"diff": { "$subtract": [ "$dayOfYear", "$todayDayOfYear"] }
}
}
pPast = {
"$project": {
"diff": 1,
"birthday": 1,
"positiveDiff": {
"$cond": {
"if": { "$lt": ["$diff", 0 ]},
"then": { "$add": ["$diff", 365] },
"else": "$diff"
},
}
}
}
pSort = {
"$sort": {
"positiveDiff": 1
}
}
pFirst = {
"$group": {
"_id": "first_birthday",
"first": {
"$first": "$$ROOT"
}
}
}
db.getCollection('tests').aggregate(pDayOfYear, pLeapYear, pPast, pSort, pFirst);
。特定の日付の次の誕生日をtodayDayOfYear
に変更することができます。
私は何らかの変更、特に読みやすさと効率の改善が可能です。
私はあなたが右に折り返したいと思いますか?だから今の12月12日だったらあなたの名前は "J"という名前でエントリーを戻したいと思うでしょう。 –
@MichaelPlattはい。 – logoff