【问题标题】:Mongoose query array of objects by _idMongoose 通过 _id 查询对象数组
【发布时间】:2017-08-15 07:14:47
【问题描述】:

我有以下架构:

const userSchema = new Schema({
  local: {
    email: {type: String, unique: true, lowercase: true, trim: true, required: true},
    password: {type: String, required: true},
  },
  Items: [{
    name: {type: String, trim: true},
    createdAt: {type: Date, default: Date.now, select: false}
  }]
});

如何根据从 url 参数接收到的特定 _id 查询 'Items'(包含对象数组)?

我有许多不同的变体,包括下面显示的一个,但它们似乎都返回包含所有对象的 Items 数组,而不仅仅是一个与 id 匹配的对象?

User.findById(req.user.id, {}, {"Items._id": req.params.id}, (err, result) => { ... }

【问题讨论】:

  • 使用projection。类似User.findOne({_id:req.user.id, "Items._id": req.params.id},{}, {"Items.$": 1}, (err, result) => { ... }
  • 仍然返回所有的项目,而不是一个单一的
  • 可能是我的猫鼬查询不正确。您可以验证它在 mongo shell 中运行它。 db.users.findOne({_id:req.user.id, "Items._id": req.params.id},{"Items.$": 1})。它将返回一个项目值。我会尝试找到正确的猫鼬查询。
  • 是的,它可以在 mongo shell 中工作,我应该在 mongoose 中使用它吗?还是有更有效的方法来编写它?谢谢
  • Np。是的,如果你知道如何转换为猫鼬。我相信这是猫鼬中的正确查询。 User.findOne({_id:req.user.id, "Items._id": req.params.id},{"Items.$": 1}, (err, result) => { ... }

标签: node.js mongodb mongoose


【解决方案1】:

您必须使用$projection 来访问嵌入式数组中的元素。查询部分找到匹配的数组元素并将占位符 $ 替换为匹配元素的数组索引,而投影部分 $ 现在将使用占位符值将数组元素投影为响应。

Mongo Shell 变体:db.users.findOne({_id:req.user.id, "Items._id": req.params.id},{"Items.$": 1})

猫鼬变种:User.findOne({_id:req.user.id, "Items._id": req.params.id},{"Items.$": 1}, (err, result) => { ... }

【讨论】:

  • 你能告诉我你的查询吗?投影中不允许混合排除和包含路径,_id 字段除外。
  • 它与您提供的相同,只是第二个对象在 "Items.$":1 前面包含 "_id":0 ,它工作正常,但我将如何修改这个整体查询以获得从结果中去掉 createdAt 属性?我想我可以在 findOne 上调用lea() 将其转换为常规对象,然后使用 delete user.Items[0].createdAt,但是在数据库端有什么方法吗?
  • 不,你不能像我说的那样。您不能在同一投影中同时包含包含 ("Items.$": 1) 和排除路径 ("Items.createdAt": 0)。你必须在猫鼬方面照顾好它。更多这里docs.mongodb.com/v3.2/tutorial/…
  • 对不起,我是 mongo 和 mongooose 的新手,在 findOne 上调用lea() 并使用 delete user.Items[0].createdAt 是解决这个问题的有效方法吗?或者有没有更有效的方法来做到这一点?
  • 我不是猫鼬方面的专家,但如果你关心性能,我个人认为这根本不是问题,那么看起来精益是你所需要的。这提供了有关精益 stackoverflow.com/questions/7503450/…stackoverflow.com/questions/15097375/… 的更多信息。我希望这能让你平静一点。
【解决方案2】:

您要做的是查询子文档。查看http://mongoosejs.com/docs/subdocs.html

你可以这样做:

User.findById(req.user.id, (err, user) => {
 let item = user.Items.id(req.params.id);
});

【讨论】:

  • 我正在寻找一种在数据库端进行操作的方法,而不是在应用程序级别
  • 我没有使用子文档,我只有一个模式,“项目”只是一个名称,就像“本地”一样
  • @linasmnew 是的,这些是子文档——这就是它们有 _id 的原因。除非您指定不需要 ID,否则它会在那里。 Mongo 中的所有对象都是文档。
  • 谢谢 不知道,user.Items.id中的'id'是指什么?因为当我在终端内查询数据库时,只有_id
  • DocumentArrays 有一个特殊的 id 方法可以通过它的 _id 来查找一个文档。 mongoosejs.com/docs/subdocs.html
猜你喜欢
  • 1970-01-01
  • 2016-09-17
  • 2014-05-13
  • 1970-01-01
  • 2021-07-02
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多