【问题标题】:Mongodb query issue using aggregate使用聚合的MongoDB查询问题
【发布时间】:2021-07-03 12:31:59
【问题描述】:

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

从以下数据集中,我想找出资源数组中包含“EC2”的文档,并仅打印出数组中的那个元素

数据

[ 
  { 
    "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"
          }
      }
    ],
  }
] 

预期输出

{
    "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
        },
      },
    ]);

^^ 这也将返回资源数组中的其他元素

【问题讨论】:

    标签: node.js mongodb mongoose nosql


    【解决方案1】:
    • $filter 迭代 resources 数组的循环并找到匹配的 resource
    • $arrayElemAt 从上面的过滤结果中获取第一个匹配元素
    • $replaceRoot 将上面的返回对象替换为根
    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

    【讨论】:

    • 嗨,谢谢,filter 为我工作。我使用了这个$filter: { input: '$resources', as: 'each', cond: { $eq: ['$$each.resource', 'EC2'] }, }, 一个问题,为什么我必须使用 2 个 $$ 符号?我假设第一个是文档,第二个是引用aseach 变量?困惑
    • 单个$ 是指当前根文档的字段,就像您可以使用$projectName 访问过滤器中的projectName 字段一样,$$ 是指$filter 的as 变量名称。
    • 有没有办法选择匹配元素的字段并返回它们?
    • 我没有得到你的确切信息,你能解释一下吗,你可以检查操场它与你的预期结果完全一样。
    • 我正在获取由过滤运算符过滤的元素。如果我想投影过滤元素的特定字段怎么办。就像我只想投影每个过滤元素的 params 属性一样。
    【解决方案2】:

    感谢@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'] },
                },
              },
            },
          },
        ]);
    

    【讨论】:

      猜你喜欢
      • 2021-12-14
      • 1970-01-01
      • 2019-10-22
      • 2019-06-18
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多