我有一个存储在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);
});
但是在查询中有更好的方法吗?
答案 0 :(得分:5)
这个问题已经差不多两年了,但我注意到人们仍然在寻找解决这个问题的方法。 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。只返回名称:' user2'你可以使用{$project: {_id: 0, 'name': '$users.name'}}
:
{name: 'user2'}
聚合管道起初并不容易掌握。我建议阅读mongodb聚合文档并一次尝试一个聚合操作。有时很难发现整个聚合管道中的错误。大多数情况下,当管道中某处出现错误时,您只是从管道中得不到结果文档。
答案 1 :(得分:2)
您应该尝试使用mongoose mongodb聚合框架:
http://mongoosejs.com/docs/api.html#aggregate-js
我建议您首先应用展开用户,然后匹配用户ID,然后项目用户名。