具有条件的 Mongoid 聚合

Mongoid aggregation with conditions

我在 Rails 5 项目中使用 mongoid 6.1.0 聚合框架。如果搜索字段(文本或 select 字段)的值不为空,我需要添加一个 $match 管道。否则,它应该被忽略并且不过滤结果。类似于:

@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)

或者更清楚:

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

问题是 if !params[:n2].blank? 无法包含在聚合框架中。还有其他替代解决方案吗?

我不知道ruby,但也许我理解你的问题。

伪代码

# 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
  }
])

更新: 正如 Aboozar Rajabi 指出的那样,如果条件为真,那么我们可以将 $match 阶段添加到管道中:

pipeline = [
    # stages
];

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

上面的伪代码(Kan A 的回答)被翻译成 Ruby 和 Mongoid 聚合框架,因为它的语法可能有点混乱,网上有一些 Mongoid 聚合示例:

 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

希望对以后看到此页面的人有所帮助。此外,此解决方案和问题中的代码将是在 Rails 或 Ruby 项目中使用 MongoDB 聚合框架的示例。