3

I have a mongodb Document like the one mentioned below

{
    "_id" : ObjectId("213122423423423"),
    "eventDateTimes" : 
     [ 
        ISODate("2015-05-26T12:18:15.000Z"), 
        ISODate("2015-05-26T12:18:14.000Z"), 
        ISODate("2015-05-26T12:00:37.000Z"), 
        ISODate("2015-05-26T12:00:36.000Z")

     ],
    "parseFlags" : 
    [ 
        false, 
        "True", 
        false, 
        false
    ],

    "eventMessages" : [ 
        "Erro1 ", 
        "Error2", 
        "Error3", 
        "Error4"       
    ]    
    }
}

I have to fetch the eventMessages based on the parseFlags array.

I have to get the index of elements in the parseFlags array where the value is "false" and then get the event messages mapping to those indexes.

The result should be the document with following parameters where parseFlag is false:

{
  id,
  EventDateTimes:[date1,date3,date4],
  ParseFlags :[false,false,false]
  eventMessages :[Error1,Error3,Error4]
}

Can you please let me know how to get this output? I am using mongodb 3.2.

Vince Bowdren
  • 8,326
  • 3
  • 31
  • 56
user3138864
  • 63
  • 1
  • 10

1 Answers1

2

Mongodb 3.4 has new array operator zip that groups the array elements based on the index

db.collectionName.aggregate({
  $project: { 
    transposed: {  
      $zip: {inputs: ["$eventDateTimes", "$parseFlags", "$eventMessages"]
    }
  }
},

  {$unwind: '$transposed'},
  {$project: {eventDateTime: {$arrayElemAt: ['$tranposed',0]}, parseFlag: 
  {$arrayElemAt: ['$transposed', 1]}}}
{$match: {parseFlag: false}}

)

For mongo 3.2 there isn't any direct way to handle the expected query. You can instead use mapReduce with custom code

db.collection.mapReduce(function(){
   var transposed = [];
   for(var i=0;i<this.eventDateTimes.length;i++){
       if(this.parseFlags[i]===false){
     transposed.push({eventDateTime: this.eventDateTimes[i], parseFlag: this.parseFlags[i]});
 }
   }
   emit(this._id, transposed);
}, function(key, values){
   return [].concat.apply([], values);
}, {out: {inline:1}})

PS: I haven't actually executed the query, but above one should give you an idea how it needs to be done.

sidgate
  • 14,650
  • 11
  • 68
  • 119