如何在mongoose中通过id查找子文档并排除某些字段

时间:2013-10-07 18:01:09

标签: mongodb mongoose

我有一个存储在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);
});

但是在查询中有更好的方法吗?

2 个答案:

答案 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文档。

  1. Shop.aggregate([{$unwind: '$users'}])
  2. $ 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,然后项目用户名。