【问题标题】:Filtering, mapping and sorting documents in aggregation pipeline在聚合管道中过滤、映射和排序文档
【发布时间】:2021-04-20 06:17:44
【问题描述】:

假设我有一个聚合管道,我能够根据需要获取所需的详细信息,但我需要按降序对名为 visits 的键的值进行排序,然后在其中挑选项目。

                {
                    $match: {
                        mobile_number: "1234567890",
                    }
                },
                {
                    $lookup: {
                        from: "visitor_logs",
                        localField: "_id",
                        foreignField: "visitor_id",
                        as: "visits",
                    }
                },
                {
                    $project: {
                        _id: 0,
                        visitor_id: "$_id",
                        first_name: "$first_name",
                        last_name: "$last_name",
                        mobile_number: "$mobile_number",
                        visits: {
                            $filter: {
                                input: "$visits",
                                as: "visit",
                                cond: {
                                    $and: [
                                        {$gte: ["$$visit.in_time", "1610609615"]},
                                        {$lte: ["$$visit.in_time", "1610615328"]},
                                    ]
                                }
                            },
                        },
                    }
                },
            ]);

示例响应

{
    "type": "SUCCESS",
    "log": [
        {
            "visitor_id": "5ffff1354351be2c600c4f94",
            "first_name": "Ayan",
            "last_name": "Dey",
            "mobile_number": "1234567890",
            "visits": [
                {
                    "_id": "5ffff3df82dc1a0e90d89a5c",
                    "in_time": "1610609615",
                    "out_time": "1610609671",
                    "checked_in_status": false,
                    "visitor_id": "5ffff1354351be2c600c4f94",
                    "visit_purpose": "Test",
                    "person_to_meet": "Someone new",
                    "__v": 0
                },
                {
                    "_id": "5ffff41a82dc1a0e90d89a5d",
                    "in_time": "1610609615",
                    "out_time": "1610609730",
                    "checked_in_status": false,
                    "visitor_id": "5ffff1354351be2c600c4f94",
                    "visit_purpose": "Test",
                    "person_to_meet": "Someone new",
                    "__v": 0
                },
                {
                    "_id": "5ffff45a82dc1a0e90d89a5e",
                    "in_time": "1610609615",
                    "out_time": "1610609919",
                    "checked_in_status": false,
                    "visitor_id": "5ffff1354351be2c600c4f94",
                    "visit_purpose": "Test",
                    "person_to_meet": "Someone new",
                    "__v": 0
                }
            ]
        }
    ]
}

现在,我正在寻找的是根据_id 以降序排列visits 字段。我的意思是挑选 visits 中的某些项目。

【问题讨论】:

  • 能否给我们看一些文档,visits 下每个数组元素的字段部分是什么,并解释一下樱桃采摘?
  • @Gibbs 更新了我的问题。你能解释一下投反对票的原因吗?
  • 尝试使用管道查找并添加 2 个阶段,第一个是 $match,第二个是 $sort。
  • @turivishal 是的,我已经这样做了(请参阅答案中的评论)。它奏效了。

标签: javascript mongodb mongoose aggregation-framework


【解决方案1】:

希望你已经解决,作为参考,这可能对你有帮助,试试lookup with pipeline

  • let 传递本地字段,管道将您的条件放入$match 阶段,您的过滤条件不需要过滤在$project 阶段。并排序 _id 按降序排列
  { $match: { mobile_number: "1234567890", } },
  {
    $lookup: {
      from: "visitor_logs",
      let: { visitor_id: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: { $eq: ["$$visitor_id", "$visitor_id"] },
            in_time: {
              $gte: "1610609615",
              $lte: "1610615328"
            }
          }
        },
        { $sort: { _id: -1 } },
        {
          $project: {
            _id: 0,
            v_id: "$_id",
            in_time: 1,
            out_time: 1,
            checked_in_status: 1,
            visit_purpose: 1,
            person_to_meet: 1
          }  
        }
      ],
      as: "visits"
    }
  },
  {
    $project: {
      _id: 0,
      visitor_id: "$_id",
      first_name: 1,
      last_name: 1,
      mobile_number: 1,
      visits: 1
    }
  }

【讨论】:

  • 出于好奇,与lookup结合使用的排序方式。
  • 根据 _id 降序访问字段。我的意思是挑选樱桃,我认为他想按降序对查找结果进行排序。
  • @turivishal,这太完美了!我正在使用项目来做大于,小于条件。这个 sn-p 简化了事情。还有一件事,我如何在访问数组中挑选项目。目前它里面有__v,visitor_id,我想删除它,并将里面的_id重命名为别的东西。
  • 您可以执行与根级别 $project 阶段相同的操作,请参阅更新后的答案。
  • @turivishal 我询问了关于插入/选择/任何种类的问题。
【解决方案2】:

一种方法是使用unwind - play

db.collection.aggregate([
  {//de-normalize
    "$unwind": "$log"
  },
  {//de-normalize
    "$unwind": "$log.visits"
  },
  {//sort
    "$sort": {
      "log.visits._id": -1
    }
  }
])

然后您可以根据您的挑选逻辑添加$match$project

樱桃采摘后,您可以使用$group将数据重塑为问题宝贝中的格式

您可以再次分组为采样here

 {
    $group: {
      _id: "$categoryData._id",
      count: {
        $sum: 1
      },
      total_price: {
        $sum: "$asset_price"
      }
    }
  }

【讨论】:

  • 好吧,我试过这种方式,但它只是破坏了响应的形状。我想把它放在目前的结构中,但要经过分类和挑选。我可以使用地图进行樱桃采摘,但不知道如何。
  • 结构是正确的,但我向您展示的示例响应是在匹配然后过滤之后。所以基本上,它是一个搜索查询,我需要输入一个手机号码并有一个日期范围作为参数。然后响应会像我展示的那样出现,并且访问数组应该按降序排列。
  • 好的!我想到了。在查找阶段使用管道对数组进行排序。
猜你喜欢
  • 1970-01-01
  • 2015-05-08
  • 1970-01-01
  • 2017-09-23
  • 2018-09-14
  • 2020-09-05
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多