【问题标题】:How to ggregate two collections and match field with array如何聚合两个集合并将字段与数组匹配
【发布时间】:2021-08-19 12:36:13
【问题描述】:

我需要对candidatosofertas 两个集合的结果进行分组,然后“合并”这些组以返回具有匹配值的数组。

我使用聚合数据和类似数据创建了这个示例,以便更容易测试:

https://mongoplayground.net/p/m0PUfdjEye4

这是对我所面临问题的解释。

我可以独立地让两组都获得所需的结果:

候选人集合:

db.getCollection('ofertas').aggregate([
{"$group" : {_id:"$ubicacion_puesto.provincia", countProvinciaOferta:{$sum:1}}} 
 ]);

这是结果...

优惠集:

db.getCollection('candidatos').aggregate([
{"$group" : {_id:"$que_busco.ubicacion_puesto_trabajo.provincia", countProvinciaCandidato:{$sum:1}}} 
 ]);

这是结果...

我需要做的是聚合这些组以根据他们的 _id 巧合合并他们的结果。我认为我在下一个聚合中以正确的方式进行,但字段countOfertas 总是返回0.0。我认为我的project $cond 有问题,但我不知道是什么问题。这是汇总:

db.getCollection('candidatos').aggregate([
    {"$group" : {_id:"$que_busco.ubicacion_puesto_trabajo.provincia", countProvinciaCandidato:{$sum:1}}},
    
            {
            $lookup: {
                from: 'ofertas',
                let: {},
                pipeline: [
                    {"$group" : {_id:"$ubicacion_puesto.provincia", countProvinciaOferta:{$sum:1}}} 
                ],
                as: 'ofertas'
            }
        },
     
       {
    $project: {
        _id: 1,
        countProvinciaCandidato: 1,
      countOfertas: {
          $cond: {
            if: {
              $eq: ['$ofertas._id', "$_id"]
            },
            then: '$ofertas.countProvinciaOferta',
            else: 0,
          }
      }
    }
  },   
        { $sort: { "countProvinciaCandidato": -1}},
        { $limit: 20 }
 ]); 

这是结果,但正如您所见,字段 countOfertas 始终为 0

欢迎任何形式的帮助

【问题讨论】:

  • 你给了我们很棒的 mongo 游乐场。但尽量避免发布图片

标签: mongodb aggregate


【解决方案1】:

非常感谢您的尝试。但在$project 中,您需要使用$reduce,这有助于循环遍历数组并满足条件

这里是代码

db.candidatos.aggregate([
  {
    "$group": {
      _id: "$que_busco.ubicacion_puesto_trabajo.provincia",
      countProvinciaCandidato: { $sum: 1 }
    }
  },
  {
    $lookup: {
      from: "ofertas",
      let: {},
      pipeline: [
        {
          "$group": {
            _id: "$ubicacion_puesto.provincia",
            countProvinciaOferta: { $sum: 1 }
          }
        }
      ],
      as: "ofertas"
    }
  },
  {
    $project: {
      _id: 1,
      countProvinciaCandidato: 1,
      countOfertas: {
        "$reduce": {
          "input": "$ofertas",
          initialValue: 0,
          "in": {
            $cond: [
              { $eq: [ "$$this._id", "$_id" ] },
              { $add: [ "$$value", 1 ] },
              "$$value"
            ]
          }
        }
      }
    }
  },
  { $sort: { "countProvinciaCandidato": -1 } },
  { $limit: 20 }
])

工作Mongo playground

注意:如果您只需要使用聚合,这很好。但我个人觉得这种做法并不好。我的建议是,您可以同时调用不同服务中的组聚合并以编程方式进行。因为$lookup很贵,当你得到海量数据时,这个性能会降低

【讨论】:

  • 非常感谢您的回复 varman。您离得太近了,但您的聚合在 countOfertas 字段中返回 0 或 1。我编辑了您的回复,使其成为正确的回复。我将 $add 更改为返回 countProvinciaOferta。我还添加了一个 $match 来删除 null 值。
【解决方案2】:

$cond 中的 $eq 将数组与 ObjectId 进行比较,因此它永远不会匹配。

$lookup 阶段结果将在 ofertas 字段中作为文档数组,因此 '$ofertas._id' 将是所有 _id 值的数组。

您可能需要在$lookup 之后使用$unwind$reduce

【讨论】:

    猜你喜欢
    • 2020-12-10
    • 2020-10-01
    • 1970-01-01
    • 2018-05-22
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多