我们具有类似于以下内容的数据库结构:
宠物主人:
/* 1 */
{
"_id" : ObjectId("5baa8b8ce70dcbe59d7f1a32"),
"name" : "bob"
}
/* 2 */
{
"_id" : ObjectId("5baa8b8ee70dcbe59d7f1a33"),
"name" : "mary"
}
宠物:
/* 1 */
{
"_id" : ObjectId("5baa8b4fe70dcbe59d7f1a2a"),
"name" : "max",
"owner" : ObjectId("5baa8b8ce70dcbe59d7f1a32")
}
/* 2 */
{
"_id" : ObjectId("5baa8b52e70dcbe59d7f1a2b"),
"name" : "charlie",
"owner" : ObjectId("5baa8b8ce70dcbe59d7f1a32")
}
/* 3 */
{
"_id" : ObjectId("5baa8b53e70dcbe59d7f1a2c"),
"name" : "buddy",
"owner" : ObjectId("5baa8b8ee70dcbe59d7f1a33")
}
我需要列出所有宠物主人以及他们所拥有的宠物数量。我们当前的查询类似于以下内容:
db.getCollection('owners').aggregate([
{ $lookup: { from: 'pets', localField: '_id', foreignField: 'owner', as: 'pets' } },
{ $project: { '_id': 1, name: 1, numPets: { $size: '$pets' } } }
]);
这行得通,但是它很慢,我问自己是否有一种更有效的查询方法?
[更新和反馈] 。感谢您的回答。该解决方案有效,但是遗憾的是,与上述查询相比,我看不到任何性能改进。显然,MongoDB仍然需要扫描整个宠物收集。我的希望是,可以以某种方式利用owner
集合上的pets
索引(存在)来获取计数(不需要触摸宠物文档),但这似乎并没有就是这种情况。
除了将计数明确存储在所有者文档中之外,是否还有其他想法或解决方案可用于快速检索“宠物计数”?
答案 0 :(得分:1)
在MongoDB 3.6中,您可以创建自定义$lookup管道并计数而不是整个pets
文档,请尝试:
db.owners.aggregate([
{
$lookup: {
from: "pets",
let: { ownerId: "$_id" },
pipeline: [
{ $match: { $expr: { $eq: [ "$$ownerId", "$owner" ] } } },
{ $count: "count" }
],
as: "numPets"
}
},
{
$unwind: "$numPets"
}
])
答案 1 :(得分:1)
您可以尝试以下汇总
db.owners.aggregate([
{ "$lookup": {
"from": "pets",
"let": { "ownerId": "$_id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$$ownerId", "$owner" ] }}},
{ "$count": "count" }
],
"as": "numPets"
}},
{ "$project": {
"_id": 1,
"name": 1,
"numPets": { "$ifNull": [{ "$arrayElemAt": ["$numPets.count", 0] }, 0]}
}}
])