首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MongoDB聚合分组填充缺少的值

MongoDB聚合分组填充缺少的值
EN

Stack Overflow用户
提问于 2020-08-06 16:50:47
回答 1查看 208关注 0票数 1

我使用的是MongoDB聚合框架。我有一个Mongo集合,里面有这样的文档:

代码语言:javascript
复制
{
  'step': 1,
  'name': 'house',
  'score': 2
}
{
  'step': 1,
  'name': 'car',
  'score': 3
}
{
  'step': 2,
  'name': 'house',
  'score': 4
}

我正在使用相同的'step‘对文档进行分组,并将'name’和'score‘推入一个对象数组。我得到的是:

代码语言:javascript
复制
{
  'step': 1,
  'scores': 
  [
      {'name':'house','score':2},
      {'name':'car','score':3}
  ]
}
{
  'step': 2,
  'scores': 
  [
      {'name':'house','score':4}
  ]
}

对于每个'step‘,我需要复制前一个'step’的值,以防'name‘不存在。我应该有这样的东西:

代码语言:javascript
复制
{
      'step': 1,
      'scores': 
      [
          {'name':'house','score':2},
          {'name':'car','score':3}
      ]
    }
    {
      'step': 2,
      'scores': 
      [
          {'name':'house','score':4},
          **{'name': 'car', 'score':3}**
      ]
    }

在第二个文档中,元素{'name': 'car‘,'score':3}已从前一个文档中复制出来,因为在'step:2’中没有文档‘car’具有'score‘。

我不知道如何使用MongoDB聚合来执行此操作。如果能帮上忙,我们将非常感激。

EN

回答 1

Stack Overflow用户

发布于 2020-08-06 17:06:59

需要在管道中使用$lookup,请一步一步地看下面。

  • $group by step和push all name in one array scores
  • push all name in names of each step,我们将在匹配条件中使用查找

代码语言:javascript
复制
db.collection.aggregate([
  {
    $group: {
      _id: "$step",
      scores: {
        $push: {
          name: "$name",
          score: "$score"
        }
      },
      names: { $push: "$name" }
    }
  },

  • $unwind scores,因为它是数组,我们将查找

代码语言:javascript
复制
  { $unwind: "$scores" },

  • $lookup让流水线的变量step(_id)和names使用表达式$expr有3个条件
    1. 检查names的大小它应该是一个(1),它的carhouse
    2. 匹配步骤号,它应该等于
    3. 匹配not in。如果car已经可用,那么它将在查找中搜索house,需要使用单独的$not$in

显示所需fields

  • lookup结果的
  • $project将存储在clone_score

代码语言:javascript
复制
  {
    $lookup: {
      from: "collection",
      let: {
        step_id: { $subtract: ["$_id", 1] },
        names: "$names"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: [{ $size: "$$names" }, 1] },
                { $eq: ["$$step_id", "$step"] },
                { $not: [{ $in: ["$name", "$$names"] }] }
              ]
            }
          }
        },
        {
          $project: {
            _id: 0,
            name: 1,
            score: 1
          }
        }
      ],
      as: "clone_score"
    }
  },

  • $group by clone_score

( step(_id) )并将所有分数推入一个数组中,保留first scores

代码语言:javascript
复制
  {
    $group: {
      _id: "$_id",
      scores: { $push: "$scores" },
      clone_score: { $first: "$clone_score" }
    }
  },

在上面的管道中,我们现在有两个独立的数组

  • scoresclone_score,我们需要在scores

中将它们连接起来

代码语言:javascript
复制
  {
    $project: {
      _id: 0,
      step: "$_id",
      scores: {
        $concatArrays: ["$scores", "$clone_score"]
      }
    }
  }
])

游乐场:https://mongoplayground.net/p/Fytf7NEU7uG

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63280021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档