【问题标题】:How to aggregate with value matched in an array then sort如何与数组中匹配的值聚合然后排序
【发布时间】:2020-12-09 23:17:56
【问题描述】:

我有这些收藏:

lists
{_id: 1, item: "a", owner: 1}
users
{_id: 1, subs: [{_id: 1, active: "Y"},{_id: 2, active: "N"}]}
subs
{_id: 1, text: "A"}
{_id: 2, text: "B"}

我想要一个包含用户信息和激活的子信息的列表结果。

{_id: 1, item: "a", owner: {_id: 1, subs: [{_id: {_id: 1, text: "A"}, active: "Y"}]}}

我还想根据“文本”字段对其进行排序。

我尝试过聚合但失败了,

db.getCollection("lists").aggregate(
[
    { 
        "$lookup" : { 
            "from" : "users", 
            "localField" : "owner", 
            "foreignField" : "_id", 
            "as" : "owner"
        }
    }, 
    { 
        "$match" : { 
            "owner.0.subs" : { 
                "$elemMatch" : { 
                    "active" : "Y"
                }
            }
        }
    }
], 
{ 
    "allowDiskUse" : false
}
);

我也在使用 Mongoose,但使用填充失败。 有什么方法可以得到我的结果?

在这里,我更新了我的聚合管道,

[
  {
    $lookup: {
      from: "users",
      as: "owner",
      let: { owner: "$owner" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$owner", "$_id"] } } },
        { $unwind: { path:"$sub", preserveNullAndEmptyArrays: false} },
        { $match: { "subs.active": "Y" } },
        {
          $lookup: {
            from: "plans",
            localField: "subs._id",
            foreignField: "_id",
            as: "subs.plans"
          }
        },
        { $unwind: { path:"$subs.plans", preserveNullAndEmptyArrays: false} },
      ]
    }
  },
  { $unwind: { path: "$owner", preserveNullAndEmptyArrays: true} },
  { '$sort': { item: 1 } },
  { '$skip': 0 },
  { '$limit': 20 } ]

【问题讨论】:

  • 您有 3 个集合,只有 1 个查找列表->用户。您至少需要另一个查找来将 subs 添加到方程中

标签: mongodb mongoose aggregation-framework aggregate mongoose-populate


【解决方案1】:

您可以将查找与管道和嵌套查找一起使用,

内部查找管道是:

  • $match您在用户集合中的所有者 ID
  • $unwind 解构 subs 数组,因为我们需要使用 subs 集合查找
  • $match subs 是否处于活动状态
  • $lookup 带有 subs 集合
  • $unwind deconstruct subs._id 我们从 subs 集合中加入
  • $group重构subs数组
  • $unwind解构owner数组
  • $sort item 和分页 $skip$limit
db.getCollection("lists").aggregate([
  {
    $lookup: {
      from: "users",
      as: "owner",
      let: { owner: "$owner" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$owner", "$_id"] } } },
        { $unwind: "$subs" },
        { $match: { "subs.active": "Y" } },
        {
          $lookup: {
            from: "subs",
            localField: "subs._id",
            foreignField: "_id",
            as: "subs._id"
          }
        },
        { $unwind: "$subs._id" },
        {
          $group: {
            _id: "$_id",
            subs: {
              $push: {
                _id: "$subs._id._id",
                text: "$subs._id.text",
                active: "$subs.active"
              }
            }
          }
        }
      ]
    }
  },
  { $unwind: "$owner" },
  { $sort: { item: 1 } },
  { $skip: 0 },
  { $limit: 20 }
], { allowDiskUse: false })

Playground


您的第二次编辑:在第一个 $unwind 中的第一次查找中有错误的键名 sub,请更正此问题,

{ $unwind: { path:"$sub", preserveNullAndEmptyArrays: false} }

{ $unwind: { path:"$subs", preserveNullAndEmptyArrays: false} }

Your Working Query

【讨论】:

  • 嗨。请检查我的新更新,我可以得到我的结果,但是在排序时,它不起作用。
  • 你到底想要什么,你想按项目名称和分页排序对吗?所以你的查询是无效的检查更新的答案。
  • 你有没有办法删除细节,只计算那些文档而没有跳过和限制?
  • 你的意思是你需要数组的总大小?,使用$size或$count
  • 你能举出使用$count / $size的例子吗?我想计算没有跳过和限制选项的聚合返回的总行数
猜你喜欢
  • 2019-07-17
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 2019-03-09
  • 1970-01-01
  • 2020-02-23
相关资源
最近更新 更多