我有一个看起来像这样的集合:
{
"_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' ]
}
从我的角度来看,当你可以在前后端实现时,最好不要在数据库端自定义投影数据。从数据库中获取数据应该是一个简单的查询或计算查询。
但是如果您愿意这样做,您的查询应该如下:
$group
- 将所有文档分组为一个。
$set
- 设置 data
字段。
2.1。
$arrayToObject
- 将对象数组转换为键值对。
2.1.1。
$map
- 迭代数组中的每个元素并转换为新数组。
2.1.1.1。
$setUnion
- 将数组组合成一个数组。替代方案:$concatArrays
.
$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"
}
])