mongodb 在 nodejs 上聚合过滤器和计数
mongodb aggregate filter and count on nodejs
我把这个 collection 命名为 "points"
[
{ 'guid': 'aaa' },
{ 'guid': 'bbb' },
{ 'guid': 'ccc' },
]
我还有一个叫 "stream"
[
{ 'title': 'pippo', 'guid': 'aaa', 'email': 'pippo@disney'},
{ 'title': 'pluto', 'guid': 'aaa', 'email': 'pluto@disney'},
{ 'title': 'goofy', 'guid': 'bbb', 'email': 'goofy@disney'},
{ 'title': 'duck', 'guid': 'aaa', 'email': 'duck@disney'},
{ 'title': 'minnie', 'guid': 'ccc', 'email': 'minnie@disney'},
]
我需要在要搜索包含字母 "o" 的 email
的位置进行聚合查询。我期望的结果是这样的
[
{ 'guid': 'aaa', items: 2 },
{ 'guid': 'bbb', item: 1 },
{ 'guid': 'ccc', item: 0 },
]
我已经这样做了
db.getCollection('points').aggregate([
{
$lookup: {
from: "stream",
localField: "guid",
foreignField: "guid",
as: "items"
}
},
{
$project: {
_id: 0,
guid: 1,
items: {
$size: "$items"
}
}
}
]);
如果我在 mysql 中,查询将是这样
SELECT DISTINCT
points.guid,
(
SELECT COUNT(*)
FROM stream
WHERE guid = stream.guid and stream.email like '%o%'
) AS items
FROM points
答案是根据评论编辑的。
您可以尝试以下聚合管道。
db.getCollection("points").aggregate([
{"$lookup":{"from":"stream", "localField":"guid", "foreignField":"guid", as:"items"}},
{"$unwind":"$items"},
{"$group":{"_id": "$guid", "guid":{"$first":"$guid"}, "emails":{"$push":"$items.email"}}},
{"$project":{"guid" :1, "emails":{"$setUnion":["$emails", [{"$literal":"io"}]]}}},
{"$unwind":"$emails"},
{"$match":{"emails":/[io]/}},
{"$group":{"_id":"$guid", "items":{"$sum":1}}},
{"$project":{"_id":0, "guid":"$_id", "items":{"$add":["$items", -1]}}}
])
示例输出:
{ "items" : 3, "guid" : "aaa" }
{ "items" : 1, "guid" : "ccc" }
{ "items" : 1, "guid" : "bbb" }
注意:我引入了一个满足匹配条件的虚拟邮箱id-'oi',以确保点采集数据不丢失。为了补偿这个虚拟字段 -1 最后从计数中减去。
我把这个 collection 命名为 "points"
[
{ 'guid': 'aaa' },
{ 'guid': 'bbb' },
{ 'guid': 'ccc' },
]
我还有一个叫 "stream"
[
{ 'title': 'pippo', 'guid': 'aaa', 'email': 'pippo@disney'},
{ 'title': 'pluto', 'guid': 'aaa', 'email': 'pluto@disney'},
{ 'title': 'goofy', 'guid': 'bbb', 'email': 'goofy@disney'},
{ 'title': 'duck', 'guid': 'aaa', 'email': 'duck@disney'},
{ 'title': 'minnie', 'guid': 'ccc', 'email': 'minnie@disney'},
]
我需要在要搜索包含字母 "o" 的 email
的位置进行聚合查询。我期望的结果是这样的
[
{ 'guid': 'aaa', items: 2 },
{ 'guid': 'bbb', item: 1 },
{ 'guid': 'ccc', item: 0 },
]
我已经这样做了
db.getCollection('points').aggregate([
{
$lookup: {
from: "stream",
localField: "guid",
foreignField: "guid",
as: "items"
}
},
{
$project: {
_id: 0,
guid: 1,
items: {
$size: "$items"
}
}
}
]);
如果我在 mysql 中,查询将是这样
SELECT DISTINCT
points.guid,
(
SELECT COUNT(*)
FROM stream
WHERE guid = stream.guid and stream.email like '%o%'
) AS items
FROM points
答案是根据评论编辑的。
您可以尝试以下聚合管道。
db.getCollection("points").aggregate([
{"$lookup":{"from":"stream", "localField":"guid", "foreignField":"guid", as:"items"}},
{"$unwind":"$items"},
{"$group":{"_id": "$guid", "guid":{"$first":"$guid"}, "emails":{"$push":"$items.email"}}},
{"$project":{"guid" :1, "emails":{"$setUnion":["$emails", [{"$literal":"io"}]]}}},
{"$unwind":"$emails"},
{"$match":{"emails":/[io]/}},
{"$group":{"_id":"$guid", "items":{"$sum":1}}},
{"$project":{"_id":0, "guid":"$_id", "items":{"$add":["$items", -1]}}}
])
示例输出:
{ "items" : 3, "guid" : "aaa" }
{ "items" : 1, "guid" : "ccc" }
{ "items" : 1, "guid" : "bbb" }
注意:我引入了一个满足匹配条件的虚拟邮箱id-'oi',以确保点采集数据不丢失。为了补偿这个虚拟字段 -1 最后从计数中减去。