Mongoose 通过 _id 查询对象数组

Posted

技术标签:

【中文标题】Mongoose 通过 _id 查询对象数组【英文标题】:Mongoose query array of objects by _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) => ... 【参考方案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 是解决这个问题的有效方法吗?或者有没有更有效的方法来做到这一点? 我不是猫鼬方面的专家,但如果你关心性能,我个人认为这根本不是问题,那么看起来精益是你所需要的。这提供了有关精益 ***.com/questions/7503450/… 和 ***.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

以上是关于Mongoose 通过 _id 查询对象数组的主要内容,如果未能解决你的问题,请参考以下文章

使用 Mongoose 从 JSON 对象数组中查询具有匹配 ID 的集合

Mongoose:通过 findOneAndUpdate 查询使用对象数组的总和更新根数据属性不起作用

从 Mongoose Find() 查询向对象数组添加属性 [重复]

从 Mongoose Find() 查询向对象数组添加属性 [重复]

Mongoose 从对象数组中查询倒数第二个项目

更新对象数组中的元素在 Mongoose 中不起作用