2015-05-18 2 views
1

Вот пример документов я использую:

{ 
    "_id" : ObjectId("554a1f5fe36a768b362ea5c0"), 
    "store_state" : 1, 
    "services" : [ 
     { 
      "id" : "XXX", 
      "state" : 1, 
      "active": true 
     }, 
     { 
      "id" : "YYY", 
      "state" : 1, 
      "active": true 
     }, 
     ... 
    ] 
} 

Я хочу, чтобы вывести новое поле с «Y», если идентификатор «XXX» и активным является истинным и «N «в любых других случаях. Сервисный элемент с «XXX» как id отсутствует в каждом документе (в этом случае выводится «N»).

Вот мой запрос на данный момент:

db.stores.aggregate({ 
    $match : {"store_state":1} 
}, 
{ $project : { 
    "XXX_active": { 
     $cond: [ { 
      $and:[ 
       {$eq:["services.$id","XXX"]}, 
       {$eq:["services.$active",true]} 
      ]},"Y","N" 
     ] } 
    } 
}).pretty() 

Но это всегда выход "N" для "XXX_active" поле.

Ожидаемый выход мне нужно:

{ 
    "_id" : ObjectId("554a1f5de36a768b362e7e6f"), 
    "XXX_active" : "Y" 
}, 
{ 
    "_id" : ObjectId("554a1f5ee36a768b362e9d25"), 
    "XXX_active" : "N" 
}, 
{ 
    "_id" : ObjectId("554a1f5de36a768b362e73a5"), 
    "XXX_active" : "Y" 
} 

Другой пример возможного результата:

{ 
    "_id" : ObjectId("554a1f5de36a768b362e7e6f"), 
    "XXX_active" : "Y", 
    "YYY_active" : "N" 
}, 
{ 
    "_id" : ObjectId("554a1f5ee36a768b362e9d25"), 
    "XXX_active" : "N", 
    "YYY_active" : "N" 
}, 
{ 
    "_id" : ObjectId("554a1f5de36a768b362e73a5"), 
    "XXX_active" : "Y", 
    "YYY_active" : "Y" 
} 

только один XXX_active на объект и не дублирует объекты, но мне нужны все объекты со XXX_active, даже если идентификатор элемента «XXX» отсутствует. Может ли кто-нибудь помочь?

+0

Можете ли вы показать нам ожидаемый выход? – chridam

+0

Выход, который мне нужен: {"_id": ObjectId ("554a1f5de36a768b362e7e6f"), "XXX_active": "Y"} {"_id": ObjectId ("554a1f5ee36a768b362e9d25"), "XXX_active": "N"} { "_id": ObjectId ("554a1f5de36a768b362e73a5"), "XXX_active": "Y"} Только один XXX_активный объект. Спасибо –

ответ

0

services Первый $unwind массив, а затем использовали $cond, как показано ниже:

db.stores.aggregate({ 
    "$match": { 
     "store_state": 1 
    } 
}, { 
    "$unwind": "$services" 
}, { 
    "$project": { 
     "XXX_active": { 
      "$cond": [{ 
       "$and": [{ 
        "$eq": ["$services.id", "XXX"] 
       }, { 
        "$eq": ["$services.active", true] 
       }] 
      }, "Y", "N"] 
     } 
    } 
},{"$group":{"_id":"$_id","XXX_active":{"$first":"$XXX_active"}}}) //group by id 
+0

Спасибо за ваш ответ, он работает, но не совсем так, как я хотел. Нужно ли группировать, если мне нужен только один результат «XXX_active» с Y или N (потому что всегда есть одна служба XXX)? С вашим решением запрос будет проверять XXX/true на всех сервисах и выводить результат для всех служб? Выход мне нужно это: { "_id": ObjectId ("554a1f5de36a768b362e7e6f"), "XXX_active": "У"} { "_id": ObjectId ("554a1f5ee36a768b362e9d25"), "XXX_active": "N", } {"_id": ObjectId ("554a1f5de36a768b362e73a5"), "XXX_active": "Y"} Только один XXX_активный объект. Спасибо, –

+0

@JulienF проверить отредактированный ответ – Yogesh

+0

спасибо, если я посмотрю на группу $, вы берете первый XXX_active, но служба XXX не всегда находится в первой позиции в массиве сервисов, с этим решением мы можем взять XXX_Active чек для право на YYY? –

0

Следующий трубопровод агрегации даст желаемый результат. Сначала вам необходимо применить оператор $unwind в поле массива services в качестве начального этапа конвейерной агрегирования. Это приведет к деконструированию поля массива services из входных документов для вывода документа для каждого элемента. Каждый выходной документ заменяет массив значением элемента.

db.stores.aggregate([ 
    { 
     "$match" : {"store_state": 1} 
    }, 
    { 
     "$unwind": "$services" 
    }, 
    { 
     "$project": { 
      "store_state" : 1, 
      "services": 1, 
      "XXX_active": { 
       "$cond": [ 
        { 
         "$and": [ 
          {"$eq":["$services.id", "XXX"]}, 
          {"$eq":["$services.active",true]} 
         ] 
        },"Y","N" 
       ] 
      } 
     } 
    }, 
    { 
     "$match": { 
      "services.id": "XXX" 
     } 
    }, 
    { 
     "$group": { 
      "_id": { 
       "_id": "$_id", 
       "store_state": "$store_state", 
       "XXX_active": "$XXX_active" 
      }, 
      "services": { 
       "$push": "$services" 
      } 
     } 
    }, 
    { 
     "$project": { 
      "_id": "$_id._id", 
      "store_state" : "$_id.store_state", 
      "services": 1, 
      "XXX_active": "$_id.XXX_active" 
     } 
    } 
]) 
+1

Спасибо, это работает! Это замедляет запрос, но результат в порядке. –

+0

Подумайте о добавлении индекса в поле 'store_state', но сначала для подтверждения, будет ли' find ({"store_state": 1}) 'использовать индекс, предположительно' 'store_state_1'', вы могли бы разместить' .explain() ' ? В противном случае конвейер агрегации должен использовать тот же план запроса, что и 'find()'. – chridam

+0

Я только что увидел, что ваше решение не совсем хорошее. Он выводит один и тот же идентификатор дважды, один с «Y» в XXX_active, если XXX присутствует и активен. Но другой идентификатор с «N» для других сервисов. –

Смежные вопросы