Aboozar Rajabi
Aboozar Rajabi

Reputation: 1793

Mongoid aggregation with conditions

I'm using the mongoid 6.1.0 aggregation framework in my Rails 5 project. I need to add a $match pipeline if the value of a search field (text or select field) is not empty. Otherwise, it should be ignored and don't filter results. Something like:

@messages = Message.collection.aggregate([
        { '$match' => {'month': {'$gte' => @fr_mnth, '$lte' => @to_mnth}}},
        { '$group' => {'_id': '$mmsi'} },
        { '$lookup' => {'from': 'ships', 'localField': "_id", 'foreignField': "mmsi", as: "ship"}},
        { '$match' => {"ship.n2": params[:n2] if !params[:n2].blank? }}
      ]).allow_disk_use(true)

or to be more clear:

if not params[:n2].blank? { '$match' => {"ship.n2": params[:n2] }}

The problem is that if !params[:n2].blank? cannot be included in the aggregation framework. Is there any other alternative solution?

Upvotes: 0

Views: 529

Answers (2)

A''
A''

Reputation: 103

I don't know ruby, but maybe I understand your problem.

Pseudo-code

# DON'T DO SO! SEE UPDATE BELOW
if your_condition is true:
  filter = { field: 'some value' }
else:
  filter = { # always true condition
    $or: [
       { field: { $exists: true } },
       { field: { $exists: false } }
    ]
  }

Message.collection.aggregate([
  # ...
  {
    "$match": filter
  }
])

UPDATE: As Aboozar Rajabi noted, if condition is true then we can just add $match stage to pipeline:

pipeline = [
    # stages
];

if condition is true:
  pipeline.push({
      $match: {
          # filter
      }
  });

Upvotes: 1

Aboozar Rajabi
Aboozar Rajabi

Reputation: 1793

The above pseudo-code (Kan A's answer) is translated to Ruby and Mongoid aggregation framework as its syntax might be a bit confusing and there're a few Mongoid aggregation examples online:

 if not params[:field].blank?
  filter = { "db_field_name": params[:field] }
else
  filter = { 
        '$or' => [ 
              { "db_field_name" => { '$exists' => true } }, 
              { "db_field_name" => { '$exists' => false } }
                 ] 
           }
end

I hope it would help the others who will see this page later. Also, this solution and the code in the question would be an example of using MongoDB aggregation framework in a Rails or Ruby project.

Upvotes: 0

Related Questions