如何使用聚合管道交换键值对

问题描述 投票:0回答:1

我有一个看起来像这样的集合:

{ 
    "_id" : ObjectId("65977bef1ccf990fe33ffc0d"), 
    "email" : "[email protected]", 
}
{ 
    "_id" : ObjectId("65977bef1ccf990fe33ffc0f"), 
    "email" : "[email protected]", 
    "phone" : "8887774455"
}
{ 
    "_id" : ObjectId("65977bef1ccf990fe33ffc10"), 
    "email" : "[email protected]"
}
{ 
    "_id" : ObjectId("65977bef1ccf990fe33ffc0e"), 
    "phone" : "6669997744"
}

我正在尝试聚合它,结果如下所示:

{
  '[email protected]': 1, // 1 can be any value (e.g. true, "yes", etc)
  '[email protected]': 1,
  '[email protected]': 1,
  '8887774455': 1,
  '6669997744': 1
}

从数据库获取数据集后,我可以使用

lodash
库来做到这一点。我只是希望使用 mongodb 来做到这一点(我的假设是它会减少资源密集度,但我可能是错的)。

所以我现在是这样做的:

Coll.aggregate([
    {
        $match: {}
    },
    {
        $project: {
            _id: false,
            email: true,
            phone: true
        }
    }
])
    .then(logs => {
        console.log(logs);
        const result = {emails: _.invertBy(logs, 'email'), phones: _.invertBy(logs, 'phone')}
        delete result.emails.undefined;
        delete result.phones.undefined;
        console.log({...result.emails, ...result.phones});

    })

是的,结果几乎就是我想要的,但是,有没有办法在数据库端做到这一点:

{
  '[email protected]': [ '0' ],
  '[email protected]': [ '1' ],
  '[email protected]': [ '2' ],
  '8887774455': [ '1' ],
  '6669997744': [ '3' ]
}
node.js mongodb aggregation-framework
1个回答
0
投票

从我的角度来看,当你可以在前后端实现时,最好不要在数据库端自定义投影数据。从数据库中获取数据应该是一个简单的查询或计算查询。

但是如果您愿意这样做,您的查询应该如下:

  1. $group
    - 将所有文档分组为一个。

  2. $set
    - 设置
    data
    字段。

    2.1。

    $arrayToObject
    - 将对象数组转换为键值对。

    2.1.1。

    $map
    - 迭代数组中的每个元素并转换为新数组。

    2.1.1.1。

    $setUnion
    - 将数组组合成一个数组。替代方案:
    $concatArrays
    .

  3. $replaceWith
    - 将输入文档替换为
    data
    对象。

db.collection.aggregate([
  {
    $group: {
      _id: null,
      phones: {
        $addToSet: "$email"
      },
      emails: {
        $addToSet: "$phone"
      }
    }
  },
  {
    $set: {
      data: {
        $arrayToObject: {
          $map: {
            input: {
              $setUnion: [
                "$emails",
                "$phones"
              ]
            },
            in: {
              k: "$$this",
              v: 1
            }
          }
        }
      }
    }
  },
  {
    $replaceWith: "$data"
  }
])

演示@Mongo Playground

© www.soinside.com 2019 - 2024. All rights reserved.