Mongodb 使用聚合的查询问题

Mongodb query issue using aggregate

我正在努力编写这个查询。

从以下数据集中,我想找出资源数组具有 'EC2' 和 的文档,仅打印出数组中的那个元素

Data:

[ 
  { 
    "projectName": "first"
    "resources": [
      {
          "resource": "EC2",
          "region": "ap-south-1",
          "params": {
              "ImageId": "ami-0bcf5425cdc1d8a85",
              "InstanceType": "t2.micro",
          }
      },
      {
          "resource": "S3",
          "region": "ap-south-1",
          "params": {
              "Bucket": "test-bucket"
          }
      }
    ],
  }
] 

Expected output:

{
    "resource": "EC2",
    "region": "ap-south-1",
    "params": {
      "ImageId": "ami-0bcf5425cdc1d8a85",
      "InstanceType": "t2.micro",
    }
}

我试过的查询:

const projects = await Project.aggregate([
      {
        $match: {
          resources: {
            $elemMatch: {
              resource: { $eq: 'EC2' },
            },
          },
        },
      },
      {
        $project: {
          resourceName: '$resources.resource',
          region: '$resources.region' // and so on
        },
      },
    ]);

^^ 这也从资源数组返回其他元素

  • $filter 迭代 resources 数组的循环并找到匹配的 resource
  • $arrayElemAt 从上面的过滤结果中获取第一个匹配元素
  • $replaceRoot 将上面的 return 对象替换为 root
const projects = await Project.aggregate([

  { $match: { resources: { $elemMatch: { resource: { $eq: "EC2" } } } } },
  // or below match is equal to above match condition
  // { $match: { "resources.resource": "EC2" } },

  {
    $replaceRoot: {
      newRoot: {
        $arrayElemAt: [
          {
            $filter: {
              input: "$resources",
              cond: { $eq: ["$$this.resource", "EC2"] }
            }
          },
          0
        ]
      }
    }
  }

])

Playground

感谢@turivishal

我想到了这个解决方案:

const projects = await Project.aggregate([
      {
        $match: {
          resources: {
            $elemMatch: {
              resource: { $eq: 'EC2' },
            },
          },
        },
      },
      {
        $project: {
          resource: {
            $filter: {
              input: '$resources',
              as: 'each', // use $$ to refer
              cond: { $eq: ['$$each.resource', 'EC2'] },
            },
          },
        },
      },
    ]);