首页 > 解决方案 > MongoDB 聚合查询 Null 字段

问题描述

在文件集合中,我的结构如下:

{
    'number': '0001',
    'name': 'user №',
    'sessions': [
        {
            'created': ISODate('2020-01-01T00:00:00'),
            'session_id': '7WGnQhFGgDgC2FDfGwbgEaLbPMMBofPFVrVh9Pn2quooAcgxZc',
            'actions': [
                {
                    'type': 'read',
                    'created': ISODate('2020-01-01T01:20:01'),
                },
                {
                    'type': 'read',
                    'created': ISODate('2020-01-01T01:21:13'),
                },
                {
                    'type': 'create',
                    'created': ISODate('2020-01-01T01:33:59'),
                }
            ],
        }
    ]
}

我需要编写一个聚合查询,以这种形式显示每个用户和每个动作类型的最后一个动作,以及它们的总和:

    {
    'number': '0001',
    'actions': [
        {
            'type': 'create',
            'last': 'created': ISODate('2020-01-01T01:33:59'),
            'count': 1,
        },
        {
            'type': 'read',
            'last': 'created': ISODate('2020-01-01T01:21:13'),
            'count': 2,
        },
        {
            'type': 'update',
            'last': null,
            'count': 0,
        },
        {
            'type': 'delete',
            'last': null,
            'count': 0,
        },
    ]
}

所以,我已经写了一个请求,但是我不知道如何输出计数== 0的动作,以及如何正确格式化输出:

[{$unwind: "$sessions"}, 
{$unwind: { path: "$sessions.actions" }}, 
{$group: {"_id": {"number": "$number",
            "type": "$sessions.actions.type"},
            "created": {"$push": "$sessions.actions.created"},
            "count": {"$sum": 1}}}, 
{$group: {"_id": {"number": "$_id.number"},
       "actions": {"$push": {"type": "$_id.type", 
       "last": {"$max": "$created"}, 
       "count": "$count"}}}}]

标签: mongodbnosqlaggregation-framework

解决方案


如果您使用的是 mongodb 服务器 4.2 或更高版本,您可以使用 set https://mongoplayground.net/p/21XH75s-usE

db.collection.aggregate([
  {
    $unwind: "$sessions"
  },
  {
    $unwind: {
      path: "$sessions.actions"
    }
  },
  {
    $group: {
      "_id": {
        "number": "$number",
        "type": "$sessions.actions.type"
      },
      "created": {
        "$push": "$sessions.actions.created"
      },
      "count": {
        "$sum": 1
      }
    }
  },
  {
    $group: {
      "_id": {
        "number": "$_id.number"
      },
      "actions": {
        "$push": {
          "type": "$_id.type",
          "last": {
            "$max": "$created"
          },
          "count": "$count"
        }
      }
    }
  },
  {
    "$set": {
      "actions": {
        "$function": {
          "body": "function(actions) {try { var act = ['read', 'create', 'delete', 'update']; act.forEach((entry) => { if (actions.filter(e => e.type === entry).length < 1) { actions.push({ 'count': 0, type: entry, last: null }); }}) }catch (e) { } return actions}",
          "args": [
            "$actions"
          ],
          "lang": "js"
        }
      }
    }
  }
])

在这里我们检查是否缺少任何动作如果缺少我们添加默认值


推荐阅读