Mongodb 聚合获取数组中的具体对象

Mongodb aggregate get specifics objects in array

如何只获取 sales 数组中与 2021-10-14 日期匹配的对象?
如果至少有一个匹配,我目前汇总 return sales 数组的所有对象。

数据集文档

{
    "name": "#0",
    "sales": [{
        "date": "2021-10-14",
        "price": 3.69,
    },{
        "date": "2021-10-15",
        "price": 2.79,
    }]
},
{
    "name": "#1",
    "sales": [{
        "date": "2021-10-14",
        "price": 1.5,
    }]
}

汇总

{
  $match: {
    sales: {
      $elemMatch: {
        date: '2021-10-14',
      },
    },
  },
},
{
  $group: {
    _id: 0,
    data: {
      $push: '$sales',
    },
  },
},
{
  $project: {
    data: {
      $reduce: {
        input: '$data',
        initialValue: [],
        in: {
          $setUnion: ['$$value', '$$this'],
        },
      },
    },
  },
}

结果

{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-15","price": 2.79},
{"date": "2021-10-14","price": 1.5}

预期结果

{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-14","price": 1.5}

您实际上需要使用 sales 数组中的 $replaceRoot or $replaceWith pipeline which takes in an expression that gives you the resulting document filtered using $arrayElemAt (or $first) and $filter

[
    { $match: { 'sales.date': '2021-10-14' } },
    { $replaceWith: {
       $arrayElemAt: [
           {
               $filter: {
                   input: '$sales',
                   cond: { $eq: ['$$this.date', '2021-10-14'] }
               }
           },
          0 
       ]
   } }
]

[
    { $match: { 'sales.date': '2021-10-14' } },
    { $replaceRoot: {
       newRoot: {
           $arrayElemAt: [
               {
                   $filter: {
                       input: '$sales',
                       cond: { $eq: ['$$this.date', '2021-10-14'] }
                   }
               },
              0 
           ]
       }
    } }
]

Mongo Playground

$project阶段,需要$filter运算符,input作为$reduce运算符来过滤文档。

{
  $project: {
    data: {
      $filter: {
        input: {
          $reduce: {
            input: "$data",
            initialValue: [],
            in: {
              $setUnion: [
                "$$value",
                "$$this"
              ],
            }
          }
        },
        cond: {
          $eq: [
            "$$this.date",
            "2021-10-14"
          ]
        }
      }
    }
  }
}

Sample Mongo Playground

使用 $unwind 怎么样:

.aggregate([
{$match: {    sales: {$elemMatch: {date: '2021-10-14'}    }  }},
{$unwind: '$sales'},
{$match: {'sales.date': '2021-10-14'}},
{$project: {date: '$sales.date', price: '$sales.price', _id: 0}}
])

这会将销售分成不同的文档,每个文档只包含一个销售,并允许您轻松匹配条件。
参见:https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/