2017-09-25 16 views
-2

私はMongoDBコレクションを持っています。このような何か:MongoDBで次の誕生日を取る

{ 
    "year" : 1985, 
    "month" : 4, 
    "day" : 16, 
    "name" : "J" 
}, 
{ 
    "year" : 1985, 
    "month" : 9, 
    "day" : 16, 
    "name" : "E" 
}, 
{ 
    "year" : 1950, 
    "month" : 11, 
    "day" : 11, 
    "name" : "M" 
}, 
{ 
    "year" : 1947, 
    "month" : 5, 
    "day" : 6, 
    "name" : "D" 
} 

私は今日始まる次の誕生日を返すMongoDBのクエリをしたいです。たとえば、今日が9月25日だった場合、私のコレクションの次の誕生日はnameのエントリに対応する11月11日で、"M"に相当します。

私は、タイプDateのフィールドを追加私の現在のyearmonthdayフィールドを削除、または任意の順序私の目標を達成するための効率的な方法を持って受け入れるだろう。

私はMongoDB v3.4を使用しています。

+0

私はあなたが右に折り返したいと思いますか?だから今の12月12日だったらあなたの名前は "J"という名前でエントリーを戻したいと思うでしょう。 –

+0

@MichaelPlattはい。 – logoff

答えて

0

最後に、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

  1. は誕生日と今日の年のシーケンシャル年を取得し、使用して$dayOfYear operator
  2. pLeapYear減算1からdayofYearフィールドの場合、birthdayはうるう年であり、各誕生日と今日の差を計算します。
  3. pPastには、誕生日に365を加えて、positiveDiffフィールドがあります。
  4. 降順で positiveDiffフィールドによって pSortソート結果で
  5. ので、私たちはpFirstでは、次の誕生日
  6. のリストを持つことができることができる唯一の最初の結果を取得します。

クエリは次のようになります。だから私は、次の誕生日の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に変更することができます。

私は何らかの変更、特に読みやすさと効率の改善が可能です。

0

このようにするには、基本的には2つのクエリが必要です。私はモンゴの専門家ではありませんが、これはあなたが今必要としているものを手に入れます/あなたを研究の正しい方向に導きます。次のように2つのクエリがあります:最初のケースでは、私は、最初の月に追加のパラメータとして、年間の昇順と第二の受注でその日を、それらを注文するんだということ

db.YOUR_COLLECTION.find({ $where: "this.year = input_year & this.month > input_month & this.day > input_day" }).sort({ month: 1, day: 1 }) 
// Gets you back all the entries that have a month greater than the input month. 

db.YOUR_COLLECTION.find({ $where: "this.year > input_year }).sort({ year: 1, month: 1, day: 1 }) 
// Gets you back all the entries that start at next year and go forward. This could probably be optimized a bit at some point. 

注意。私もすべての行を返しています。実際には、1つの結果の制限のようなことをしたいことがあります。いずれにしても、次の日付が来年にラップされないケースを処理するために、最初のクエリを実行する必要があります。その結果が返されない場合は、2番目のクエリが翌年に開始され、前方に検索されます。これであなたの質問に完全に答えることができない場合は、私に知らせてください。

関連する問題