我有一个文档存储在 mongodb 中:
shop: {
_id: '...'
title: 'my shop'
users: [
{
_id: '...',
name: 'user1',
username: '...'
},
{
_id: '...',
name: 'user2',
username: '...'
}
]
}
我使用此查询通过他的 id 获取子文档用户:
Shop.findOne({'users._id': userId}, {'users.$': 1}, function (err, user) {
console.log(user);
});
输出:
{ _id: ...,
users:
[{
name: 'user1',
username: '...',
_id: ...
}]
}
如何过滤结果以仅返回用户名。 我现在的做法:
Shop.findOne({'users._id': userId}, {'users.$': 1}, function (err, shop) {
shop = shop.toObject()
user = shop.users[0]
filtered = {
name: user.name
}
callback(filtered);
});
但是有没有更好的方法在查询中完成这一切?
最佳答案
这个问题已经提出将近两年了,但我注意到人们仍在寻找解决这个问题的方法。 fernandopasik 的回答对我帮助很大,但缺少有关如何使用建议的聚合操作的代码示例。这就是为什么我发布更详细的答案。 我使用的文档是:
{
_id: '...'
title: 'my shop'
users: [
{
_id: 'user1Id',
name: 'user1',
username: '...'
},
{
_id: 'user2Id',
name: 'user2',
username: '...'
}
]
}
我提出的解决方案(在阅读了有关聚合的 mongodb 文档之后)是:
Shop.aggregate([
{$unwind: '$users'},
{$match: {'users._id': 2}},
{$project: {_id: 0, 'name': '$users.name'}}
]);
要了解聚合是如何工作的,最好一次尝试一个操作并阅读该操作的 mongodb 文档。
Shop.aggregate([{$unwind: '$users'}])
$unwind 解构用户数组(不要忘记在数组名称中包含 $),所以你最终得到:
{
_id: '...',
title: 'my shop',
users: {
_id: 'user1Id',
name: 'user1',
username: '...'
}
}
{
_id: '...',
title: 'my shop',
users: {
_id: 'user2Id',
name: 'user2',
username: '...'
}
}
2。在聚合管道(本例中的两个文档)上使用 {$match: {'users._id': 'user2Id'}}
将返回 users._id 为 'user2Id' 的整个文档:
{
_id: '...',
title: 'my shop',
users: {
_id: 'user2Id',
name: 'user2',
username: '...'
}
}
3。只返回 name: 'user2' 你可以使用 {$project: {_id: 0, 'name': '$users.name'}}
:
{name: 'user2'}
聚合管道一开始并不容易掌握。我建议通读 mongodb 聚合文档并一次尝试一个聚合操作。有时很难发现整个聚合管道中的错误。大多数情况下,当管道中某处出现错误时,您根本无法从管道中获得任何结果文档。
关于mongodb - 如何在 mongoose 中通过 id 查找子文档并排除某些字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19231536/