2015-12-16 1 views
1

Я пытаюсь использовать операцию $ filter на вложенном массиве и не могу заставить его работать правильно.

Работает ли операция $ fliter с вложенными массивами?

Это моя коллекция MongoDB

{ 
    metrics: [ 
     {hits: 4 ,data: [ 
     {"status_Code" : 200, "response_time" : 245 }, 
     {"status_Code" : 200, "response_time" : 343}, 
     {"status_Code" : 501, "response_time" : 345 }, 
     {"status_Code" : 200, "response_time" : 234}, 
     {"status_Code" : 0, "response_time" : -1, }, 
    ] 
     }, 
     {hits: 2 ,data: [ 
     {"status_Code" : 200, "response_time" : 245}, 
     {"status_Code" : 200, "response_time" : 343}, 
     {"status_Code" : 0, "response_time" : -1}, 
     {"status_Code" : 0, "response_time" : -1}, 
     {"status_Code" : 0, "response_time" : -1}, 
     ]} 
    ], 
} 

Совокупные Запрос:

db.collection.aggregate([ 
{ 
    $project: { 
     metrics: { 
      $filter: { 
       input: "$metrics.data", 
       as: "mdata", 
       cond: {$gt: ["$$mdata.response_time", -1]} 
      } 
     } 
    } 
} 
]); 

Желаемая Выход:

{ 
    metrics: [ 
     { 
      hits: 4 , 
      data: [ 
       {"status_Code" : 200, "response_time" : 245 }, 
       {"status_Code" : 200, "response_time" : 343}, 
       {"status_Code" : 501, "response_time" : 345 }, 
       {"status_Code" : 200, "response_time" : 234}, 
      ] 
     }, 
     { 
      hits: 2 , 
      data: [ 
       { "status_Code" : 200, "response_time" : 245}, 
       {"status_Code" : 200, "response_time" : 343}, 
      ] 
     } 

    ] 
} 

ответ

1

Вы не можете использовать оператор $filter здесь, потому что в под-документах массива «метрики» нет поля с именем «response_time».

Для использования $filter вам понадобится $unwind массив «метрики».

db.collection.aggregate([ 
    { '$match': { 'metrics.data.response_time': { '$gt': -1 } } }, 
    { '$unwind': '$metrics' }, 
    { '$project': { 
     'metrics': { 
      '$filter': { 
       'input': "$metrics.data", 
       'as': "mdata",     
       'cond': { '$gt': [ '$$mdata.response_time', -1 ] }    
      }   
     } 
    }} 
]) 

Другой вариант заключается в использовании $redact, как показано here.

db.collection.aggregate([ 
    { '$match': { 'metrics.data.response_time': { '$gt': -1 } } }, 
    { '$redact': { 
     '$cond': [ 
      { '$or': [ 
       { '$gt': [ '$response_time', -1 ] }, 
       { '$not': '$response_time' } ] 
      }, 
      '$$DESCEND', 
      '$$PRUNE' 
     ] 
    }} 
]) 
Смежные вопросы