2013-10-07 47 views
3

我已存储在MongoDB中的一个文件:如何找到在猫鼬ID子文档,并排除某些领域

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); 
}); 

但有一个更好的方式来做到这一切在查询?

回答

2

这个问题差不多两岁了,但我注意到人们仍然在寻找解决这个问题的办法。 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文档。

  1. Shop.aggregate([{$unwind: '$users'}])

$放松解构用户阵列(不要忘了包括$阵列名称),所以你最终:

{ 
    _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只返回名称:“用户2”,你可以使用{$project: {_id: 0, 'name': '$users.name'}}

{name: 'user2'} 

聚集管道是不容易在第一把握。我建议通读mongodb聚合文档并尝试一次聚合操作。有时很难发现整个聚合管道中的错误。大多数情况下,当流水线中存在错误时,您只需从管道中获取任何结果文档。