2016-12-01 4 views
0

にネストされた日付範囲を照会するためにどのように、ここに私のデータがあります:[OK]をMongoid

"stats" : [ 
    { 
     "campaign_id" : "some_id", 
     "log_id" : "some_id", 
     "agent" : "some_id", 
     "office" : "some_id", 
     "hq" : "some_name", 
     "seller" : "some_name", 
     "status" : "live", 
     "phases" : [ 
      { 
       "phase" : "main_phase", 
       "banners" : [ 
        { 
         "banner_id" : "some_id_same_as_below", 
         "split_var" : "light", 
         "reports" : [ 
          { 
           "date" : "2016-11-25", 
           "banner" : "some_id_same_as_above", 
           "cost" : "0.231", 
           "impressions" : 14, 
           "clicks" : 0 
          }, 
      ... 

そして、私はすべてのレポートのためにデータベースを照会する必要があります。"date" : "2016-11-25"については

"reports" : [ 
{ 
    "date" : "2016-11-25", 
    "banner" : "some_id_same_as_above", 
    "cost" : "0.231", 
    "impressions" : 14, 
    "clicks" : 0 
}, 

日内範囲。日付範囲については、私はこれを持っています:

start_month = DateTime.current.beginning_of_month - 1.month 
end_month = DateTime.current.end_of_month - 1.month 

これは私に前月の開始と終了を与えます。この範囲内のレポート(統計、フェーズ内のネストされた値など)を持つすべてのドキュメントを検索するにはどうすればよいですか?

アイデア?

EDIT

データをDBに挿入されている方法を変更することが提案されてきたが、残念ながら私は(サードパーティのサービス/ APIによって行われる)データが挿入されているどのように制御することはできません。

答えて

0

あなたは、例えば、標準のDateオブジェクトの代わりに、フォーマットされた文字列、ISODate形式でのMongoDB店として日付を格納することができます

db.collection.insert({date: new Date()}); 

のようなフィールドがあります。そして、

{ "date" : ISODate("2016-11-15T15:50:15.167Z") } 

をお2つの範囲の間でクエリを実行する必要がある場合は$と演算子を使用します。

など:

// Return all documents in collection with a date between 11-1-2016 and 12-1-2016 
db.collection.find({ 
    $and: [ 
     { date: { $gte: ISODate("2016-11-01T00:00:00.000Z") } }, 
     { date: { $lt: ISODate("2016-12-01T00:00:00.000Z") } } 
    ] 
}) 

EDIT:あなたのコレクションを変更することはできません場合は、あなたが正規表現スタイルの検索を行うことができます...例えば

db.collection.find({ 
    "stats.phases.banners.reports.date": /2016-11/ 
}); 

はそれ以来、2016年11月のためのすべての文書を返します。ここで

: "2016から11"

EDIT AGAIN含むすべての文字列に一致しますあなたが原因あなた重くネストされた配列構造体に巻き戻さをたくさんしなければならない、すなわち

{ 
    "reports" : { 
     "date" : "2016-11-23", 
     "banner" : ObjectId("58404a9450b5412e92ebbb97"), 
     "cost" : "0.231", 
     "impressions" : 14, 
     "clicks" : 0 
    } 
}, 
{ 
    "reports" : { 
     "date" : "2016-11-25", 
     "banner" : ObjectId("58404a9450b5412e92ebbb97"), 
     "cost" : "0.231", 
     "impressions" : 14, 
     "clicks" : 0 
    } 
} 

注...

db.collection.aggregate([ 
    { $unwind: "$stats" }, 
    { $unwind: "$stats.phases" }, 
    { $unwind: "$stats.phases.banners" }, 
    { $unwind: "$stats.phases.banners.reports" }, 
    { $match: { "stats.phases.banners.reports.date": /2016-11/ } }, 
    { $project: { _id: 0, reports: "$stats.phases.banners.reports" } } 
]) 
0
上記の形式で文書を返すために集約フレームワークを使用したソリューションです。

dateのフィールドをISODateオブジェクトとして格納し、次に$lt$lte$gt、などの比較演算子を使用する必要があります。ここ は、データを挿入する方法について説明します。次の

db.test.insert({ 
    "stats": [ 
    { 
     "campaign_id": "some_id", 
     "log_id": "some_id", 
     "agent": "some_id", 
     "office": "some_id", 
     "hq": "some_name", 
     "seller": "some_name", 
     "status": "live", 
     "phases": [ 
     { 
      "phase": "main_phase", 
      "banners": [ 
      { 
       "banner_id": "some_id_same_as_below", 
       "split_var": "light", 
       "reports": [ 
       { 
        "date": ISODate("2016-11-25T00:00:00.0Z"), 
        "banner": "some_id_same_as_above", 
        "cost": "0.231", 
        "impressions": 14, 
        "clicks": 0 
       } 
       ] 
      } 
      ] 
     } 
     ] 
    } 
    ] 
}) 

stats.phases.banners.reports.dateである2016年11月25〜15 12月2016

db.test.find({"stats.phases.banners.reports.date": {$lt: ISODate("2016-11-25T00:00:00.0Z"), $gt: ISODate("2016-12-25T00:00:00.0Z")}}) 
文書を検索するための照会であります