1

I've following collection in my MongoDB database

clat_output

{
"_id" : ObjectId("59fc6492421aa91e3e71d753"),
"output" : [ 
    {
        "time" : "100",
        "clat" : "127"
    }, 
    {
        "time" : "254",
        "clat" : "294"
    }, 
    {
        "time" : "354",
        "clat" : "437"
    }
    ...
    ...
]
}

I want to retrieve clat_output with a condition that time in clat_output should be in between a given range.

For example

I want to fetch clat_output having _id = ObjectId("59fc6492421aa91e3e71d753") with given time interval as 1 to 300

So it should give following output

{
"_id" : ObjectId("59fc6492421aa91e3e71d753"),
"output" : [ 
    {
        "time" : "100",
        "clat" : "127"
    }, 
    {
        "time" : "254",
        "clat" : "294"
    }
]
}

When I run the following query in mongodb console then it's giving me desired result.

db.clat_output.aggregate({
  '$match' : {"_id" : ObjectId("59fc6492421aa91e3e71d753")}}, {
    '$addFields' : {
      'output' : {
        '$filter' : {
            'input' : '$output',
            'as' : 'result',
            'cond' : { 
                '$and' : [
                  {'$gte' : ['$$result.time', '1']},
                  {'$lte' : ['$$result.time', '300']}
                ]
            }
        }
    }
  }
});

But when I converted the same aggregate query into raw query in laravel, it's showing output as empty array. Following is my query in laravel

public function clat_output($id, $start, $end) {
  $query = [
    ['$match' => ["_id" => $id]], [
       '$addFields' => [
          'output' => [
             '$filter' => ['input' => '$output', 'as' => 'result',
                'cond' => [
                   '$and' => [
                      ['$gte' => ['$$result.time', $start]],
                      ['$lte' => ['$$result.time', $end]]
                   ]
                ]
             ]
          ]
       ]
    ]
  ];

  $result = self::raw(function ($collection) {
    return $collection->aggregate($query);
  });
  return $result;
}
1
  • Though possibly not directly related, your data is flawed. You have 'time' as a "string" and as such a value like '5' does not fall "between" the values of '1' and '300' since it begins with '5' and as a "string" that is not within the range. You actually want "numeric" values if you want to query for "numeric ranges". So you really should convert the data. Commented Nov 8, 2017 at 19:53

1 Answer 1

1

It seems your query is perfect. The only thing that I'm bit sceptical is about type mismatch of $start and $end. To validate you can use following code in mongo console.

function printSchema(obj) { 
  for(var key in obj) { 
    if(key === 'output') { 
       print('time',typeof obj[key][0]['time']); 
       break; 
    } 
  } 
}
var obj = db.clat_output.findOne();
printSchema(obj);

In php check data type of $start and $end by using following command

echo gettype($start),"\n";
echo gettype($end);

If there is mismatch in data type then you need to do type conversion.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes there was a type mismatch. time field was stored as string in database and I was comparing it with integer in php.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.