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

ffdz8vbo  于 11个月前  发布在  Node.js
关注(0)|答案(1)|浏览(92)

我有一个收藏,看起来像这样:

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

    })


是的,结果几乎是我想要的,但是,再一次,有没有一种方法可以在db端做到这一点:

{
  '[email protected]': [ '0' ],
  '[email protected]': [ '1' ],
  '[email protected]': [ '2' ],
  '8887774455': [ '1' ],
  '6669997744': [ '3' ]
}

x3naxklr

x3naxklr1#

从我的Angular 来看,如果可以在前端/后端实现投影,最好不要在数据库端定制投影数据。从数据库中获取数据应该是一个简单的查询或计算查询。想象一下,当数据库中有大量记录时,这会导致查询性能低下,并使数据库过载。
但如果你热衷于这样做,你的查询应该如下:

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

字符串
Demo @ Mongo Playground

相关问题