ruby-on-rails Mongoid:获取缺少至少一个类别的文档的用户

fnvucqvd  于 2023-03-20  发布在  Ruby
关注(0)|答案(1)|浏览(107)

bounty将在2天后过期。回答此问题可获得+50的声望奖励。Samy Kacimi正在寻找规范答案

我在ORM中使用Ruby On Rails和Mongoid。
我有一个User类和一个Document类,用户有_many个文档,一个文档有一个类别,有多个类别,但是有些是强制的。
我要检索以下所有用户:

  • 缺少某个强制类别中的文档
  • 或者根本没有文档的用户

以下是我目前为止对聚合所做的尝试,但这并不奏效:

def self.without_all_required_documents
  subquery = Document.collection.aggregate([
    { "$match" => { "user_id" => { "$ne" => nil }, "category" => { "$in" => required_categories } } },
    { "$group" => { "_id" => "$user_id", "categories" => { "$addToSet" => "$category" } } },
    { "$project" => { "_id" => 1, "missing_categories" => { "$setDifference" => [required_categories, "$categories"] } } },
    { "$match" => { "missing_categories" => { "$ne" => [] } } },
    { "$project" => { "_id" => 1 } }
  ])

  where(
    :"$or" => [
      { :id.in => subquery.map { |doc| doc["_id"] } },
      { :"$and" => required_categories.map { |cat| { :"documents.category" => cat } } },
      { :"$expr" => { :"$eq" => [{ :"$size" => { :"$ifNull" => ["$documents", []] } }, 0] } }
    ]
  )
end

我得到了有文档的记录,有所有必需文档的记录,没有没有文档的记录。

rnmwe5a2

rnmwe5a21#

要检索缺少某个强制类别中的文档的所有用户或根本没有文档的用户,可以使用以下查询:

User.collection.aggregate([
  {
    "$lookup": {
      "from": "documents",
      "localField": "_id",
      "foreignField": "user_id",
      "as": "documents"
    }
  },
  {
    "$match": {
      "$or": [
        {
          "$and": [
            { "documents.category": { "$in": ["mandatory_category1", "mandatory_category2"] } },
            { "documents": { "$not": { "$elemMatch": { "category": "mandatory_category1" } } } },
            { "documents": { "$not": { "$elemMatch": { "category": "mandatory_category2" } } } }
          ]
        },
        { "documents": { "$size": 0 } }
      ]
    }
  }
])

下面是它的工作原理:

  • $lookup阶段使用user_id字段作为外键对documents集合执行左外连接。
  • $match阶段根据两个条件过滤结果:
  • $or运算符组合了两个条件:
  • 第一个条件选择在一个强制类别中至少有一个文档,但至少缺少一个文档的用户。
  • 第二个条件选择没有任何文档的用户。
  • 第一个条件是用$and运算符指定的,它包括三个子条件:
  • 第一个子条件选择类别在强制类别列表中的文档。
  • 第二个和第三个子条件使用$not运算符和$elemMatch来选择没有特定类别的文档。
  • 第二个条件选择文档数组为空的用户。

注意,您需要将“mandatory_category1”和“mandatory_category2”替换为强制类别的实际名称。

相关问题