具有所有嵌入文档匹配条件的 Mongoid 查询记录

Mongoid query records that have all their embedded documents matching a criteria

假设我有这样的模型

class Band
  include Mongoid::Document
  embeds_many :albums
end

class Album
  include Mongoid::Document
  field :name, type: String
  field :producer, type: String
  embedded_in :band
end

我想得到的是所有专辑都是由“George Martin”制作的乐队。

我试过 Band.where('albums.producer' => 'George Martin') 但它匹配所有至少有一次乔治·马丁作为制作人的乐队。

示例:

这个乐队应该匹配(因为他们所有的专辑都是乔治·马丁制作的):

{
  "_id" : ObjectId("blabla"),
  "albums" : [
    {
      "_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
      "name" : "Violator",
      "producer" : "George Martin"
    }
  ]
}

这个乐队不应该匹配(因为专辑“+”已经由另一个制作人制作):

{
  "_id" : ObjectId("blablabla"),
  "albums" : [
    {
      "_id" : ObjectId("album1"),
      "name" : "/",
      "producer" : "George Martin"
    },
    {
      "_id" : ObjectId("album2"),
      "name" : "+",
      "producer" : "Another producer"
    }
  ]
}

您可以使用 $reduce 来处理您的 albums 数组。通过设置初始值true,当一个条目不等于时,可以有条件地将值设置为false “George Martin”通过使用累加器的 $and 条件。 $match累加器执行过滤的最终结果。

{
    "$reduce": {
        "input": "$albums",
        "initialValue": true,
        "in": {
        $and: [
            "$$value",
            {
            $eq: [
                "$$this.producer",
                "George Martin"
            ]
            }
        ]
        }
    }
}

这里是Mongo playground供大家参考。