2017-06-15 4 views
1

finById()select()find()をマングースにすることはできますか?私はこのようなものを試していて、日付を受け入れず、代わりにfamilyStatsコレクション内のすべてのオブジェクトを返します。日付範囲内の配列ドキュメントを返す

module.exports.getFamilyStatsPast = function (req, res) { 
    var id = req.params.id; 
    var days = req.params.days; 

    var pastDate = new Date(); 
    pastDate.setDate(pastDate.getDate() - days).toISOString(); 
    var currentDate = new Date().toISOString(); 

    Worksets 
     .findById(id) 
     .select('familyStats') 
     .find({ 
      createdOn : { 
       $gte: pastDate, 
       $lte: currentDate 
      } 
     }) 
     .exec(function (err, doc){ 
      var response = { 
       status: 200, 
       message: [] 
      }; 
      if (err){ 
       console.log("Error finding Workset"); 
       response.status = 500; 
       response.message = err; 
      } else if(!doc){ 
       console.log("Workset id not found in database", id); 
       response.status = 404; 
       response.message = {"message": "Workset Id not found."} 
      } 
      if(doc){ 
       console.log("Found workset: ", doc); 
       res 
        .status(response.status) 
        .json(doc) 
      } else { 
       res 
        .status(response.status) 
        .json(response.message); 
      } 
     }); 
}; 

私は基本的に を取得しようとしています - ワークセットコレクションから配列がfamilyStats と呼ばれる - その配列から、私は先週から今まででpastDatecurrentDateの間に作成されたばかりのオブジェクトをしたいです。

私が間違っていることは何ですか?

ここに私のマングースデータスキーマです:

var familyStatsSchema = new mongoose.Schema({ 
    suspectFamilies: [{ 
     name: String, 
     size: String, 
     sizeValue: Number, 
     instances: Number, 
     elementId: Number 
    }], 
    totalFamilies: Number, 
    unusedFamilies: Number, 
    oversizedFamilies: Number, 
    inPlaceFamilies: Number, 
    createdBy: String, 
    createdOn: Date 
}); 

var healthCheckSchema = new mongoose.Schema({ 
    onOpened: [worksetEventSchema], 
    onSynched: [worksetEventSchema], 
    itemCount : [worksetItemSchema], 
    viewStats: [viewStatsSchema], 
    linkStats: [linksStatsSchema], 
    familyStats: [familyStatsSchema] 
}); 

mongoose.model('Worksets', healthCheckSchema); 
+0

質問に答えられていないと思われる回答がありますか?もしそうなら、正確に答えなければならないものを明らかにするために答えにコメントしてください。実際にあなたが質問した質問に答えた場合は、[あなたの回答を受け入れる](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)に質問してください。聞いてください。 –

答えて

2

あなたが望むすべては、文書内の配列から特定の日付範囲内からデータを取得する場合、あなたが必要とするすべてが集約フレームワークから$filter操作です。

var id = req.params.id; 
var days = parseInt(req.params.days); 

var now = new Date(), 
    firstDate = new Date(now.valueOf() - (1000 * 60 * 60 * 24 * days)); 

Worksets.aggregate([ 
    { "$match": { 
    "_id": ObjectId(id), 
    "familyStats": { 
     { "$elemMatch": { "createdOn": { "$gte": firstDate, "$lt": now } } } 
    }}, 
    { "$project": { 
    "familtStats": { 
     "$filter": { 
     "input": "$familyStats", 
     "as": "el", 
     "cond": { "$and": [ 
      { "$gte": [ "$$el.createdOn", firstDate ] }, 
      { "$lt": [ "$$el.createdOn", now ] } 
     ]} 
     } 
    } 
    }} 
],function(err, results) { 
    // work with response 
}) 

我々は、クエリ条件を指定.find()のようにちょうど同じように動作します初期$match条件があります。 $elemMatchで日付範囲条件を追加しています。$elemMatchの範囲内に日付がない場合、文書を返すポイントがないため、「範囲式」は実際には配列要素にAND条件が適用されているためです。それがなければ、配列全体がではなく「それらの間に何かがある場合」ではなく、それらの条件を満たすかどうかを単に尋ねるだけです。

また、ObjectIdコンストラクタがここに注目してください。 _idフィールドのMongooseの "autocast"値は通常 "文字列"からのものですが、集約フレームワークではこれを自分自身で行うことはできません。あなたは "キャスト"を手動で行う必要があります。したがってSchema.Typesからインポートし、ここで受け取ったパラメータに適用します。

_id制約を含まない可能性があるドキュメントが一致した後、$projectパイプラインステージは、返された結果の「シェイプ」を決定します。標準のクエリプロジェクションと同様に、ここで実際に必要な「すべての」フィールドを含める必要があります。例として、私は問題の配列を返すだけです。

$filter「が文書(複数可)」条件に一致するかどうかとは対照的に、この時間を除いて、それらが実際「アレイ要素自体」に適用され、$matchに存在したような論理条件の同じ種類を適用。指定された基準を満たさないものは、返される配列から削除されます。

これは、通常の.find()クエリとほぼ同じパフォーマンスの操作を提供しますが、使用される演算子は、結果がサーバーから返される前の配列から日付範囲外の不要なコンテンツを削除できる。

あなたのような大きな文書では、他の配列と同様に実行する通常の操作でなければなりません。