1

私は現在、このスキーマを持っているMongoDBのマッチとスライス複数の子の配列

var dataSchema = new Schema({ 
hid: { type: String }, 
sensors: [{ 
    nid: { type: String }, 
    sid: { type: String }, 
    data: { 
     param1: { type: String }, 
     param2: { type: String }, 
     data: { type: String } 
    }, 
    date: { type: Date, default: Date.now } 
}], 
actuators: [{ 
    nid: { type: String }, 
    aid: { type: String }, 
    control_id: { type: String }, 
    data: { 
     param1: { type: String }, 
     param2: { type: String }, 
     data: { type: String } 
    }, 
    date: { type: Date, default: Date.now } 
}], 
status: [{ 
    nid: {type: String}, 
    status_code: {type: String}, 
    date: { type: Date, default: Date.now } 
}], 
updated: { type: Date, default: Date.now }, 
created: { type: Date } 
}); 

私が構築しようとしているクエリ」は、「HID」でスキーマを検索するだけ「センサー」から選択する必要がありますアクチュエーター "と"ステータス "は、私が提供するnidに一致するオブジェクトを配列し、各アレイの結果を10要素に制限します。

答えて

1

実際には、「1」が行う場合は複数のパイプラインフェーズを使用しないでください。インクルードするすべてのパイプラインステージは、データをもう一度処理するため、処理に「時間」を効果的に追加します。

だから何論理的に「シングル」のステージで働く、「シングル」の段階にとどまる必要があります。

Data.aggregate([ 
    { "$match": { "hid": hid } }, 
    { "$project": { 
     "sensors": { 
      "$slice": [ 
       { "$filter": { 
        "input": "$sensors", 
        "as": "sensor", 
        "cond": { "$eq": [ "$$sensor.nid", nid ] } 
       }}, 
       -10 
      ] 
     }, 
     "actuators": { 
      "$slice": [ 
       { "$filter": { 
        "input": "$actuators", 
        "as": "actuator", 
        "cond": { "$eq": [ "$$actuator.nid", nid ] } 
       }}, 
       -10 
      ] 
     }, 
     "status": { 
      "$slice": [ 
       { "$filter": { 
        "input": "$status", 
        "as": "status", 
        "cond": { "$eq": [ "$$status.nid", nid ] } 
       }}, 
       -10 
      ] 
     }, 
     "updated": 1, 
     "created": 1 
    }} 
]) 

はまた、それが"_id"ので、介在物中の"_id": 1を使用する必要はありません、常に明示しない限り、含まです"除外された"。

パフォーマンスが悪いため、不必要なステージを作成しないようにすることが主なケースです。この良い指標は以下のとおりです。

$project続い
  • $project、通常は、1つの段階でこれを行うことができることを意味します。 $group続い
  • $projectはおそらく、とにかく「オプティマイザ」により圧縮を取得するつもりされていますが、両者を組み合わせるのが習慣に取得する「必要があります」。 $match続い
  • $projectは、おそらく代わりに、単一の段階で$redactを使用する必要があることを示す必要があります。 $projectは、計算に基づいてフィールドを作成する可能性が高いため、$matchで考慮されていました。

そして最後に:$match

  • $unwind、本当に$unwind "前" $projectで​​されている必要があります。実際には、文書内で「フィルタリング」する時間が大幅に短縮され、すでにフィルタリングされたコンテンツからの出力が少ないため、$unwindの処理にかかるコストも節約できます。

しかし、もう一つ:

  • 「アレイ」は、$mapなどの操作、​​、$sliceさらには「集合演算子」の全てが必ずしも互いに「インライン」に使用されるべきですそれらが同じ配列内容を操作している場合には、 $group段階内

    { "$sum": { "$sum": "$array" } } 
    

    構造:同じことが今現在でもこれらは、配列自体に、そして頻繁に見ている奇妙だが効果を直接操作できることを$sumまたは$maxでラップに適用されます。

+0

説明と提案に感謝します – danielebuso

1

これは、集約フレームワークで実現できます。このような クエリを見て:

Data.aggregate([ 
      { "$match": { "hid": hid } }, 
      { "$project": { 
       "_id": 1, 
       "sensors": { 
        "$filter": { "input": "$sensors", "as": "sensor", "cond": { "$eq": [ "$$sensor.nid", nid ] } } 
       }, 
       "actuators": { 
        "$filter": { "input": "$actuators", "as": "actuator", "cond": { "$eq": [ "$$actuator.nid", nid ] } } 
       }, 
       "status": { 
        "$filter": { "input": "$status", "as": "state", "cond": { "$eq": [ "$$state.nid", nid ] } } 
       }, 
       "updated": 1, 
       "created": 1 
      }}, 
      { "$project": { 
       "_id": 1, 
       "sensors": { 
        "$slice": [ "$sensors", -10 ] 
       }, 
       "actuators": { 
        "$slice": [ "$actuators", -10 ] 
       }, 
       "status": { 
        "$slice": [ "$status", -10 ] 
       }, 
       "updated": 1, 
       "created": 1 
      }} 
     ]).exec(function(err,data) { 
     }); 

それは、アレイから提供さnidに一致する要素のみを選択するために、スキーマを見つけること$filter$matchを使用し、その後から、最後の10個の要素を選択する$sliceを使用していますフィルタリングされた配列

+1

ここでは結論に至りましたが、ここではパフォーマンスに大きな影響を及ぼすいくつかの構造的な問題があります。 –

+0

説明と提案に感謝します:) – danielebuso

関連する問題