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

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

但是有没有更好的方法在查询中完成这一切?

最佳答案

这个问题已经提出将近两年了,但我注意到人们仍在寻找解决这个问题的方法。 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'}])

$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/

相关文章:

MongoDB(Mgo v2)投影返回父结构

javascript - findOneAndUpdate Mongoose 查询返回旧数据库值

javascript - 无法在 Javascript 中检索对象属性

javascript - Meteor 中用于搜索和显示文档的标准模式

javascript - MEAN.JS——请求对象、Express Controller 和 Mongoose 模式

javascript - "$lookup with ' 管道 ' may not specify ' 本地字段 ' or ' 国外字段 '"

javascript - 无法在 REST API 之外使用 Mongoose 查询 MongoDB

javascript - 按 MongoDB 返回的值合并两个对象数组

linux - mongos 的初始化脚本和 MongoDB 分片的配置服务器

java - 如何使用java代码自动增加mongodb中的字段?