Mongoose/Mongo中查找ObjectId数组

13

我在MongoDB中有这个项目:

[ 
  { 
    title: 'Product Name',
    _id: 5052843e023273693300013c,
    description: 'This is a fake description',
    categories: [ 5052843e023273693300010a ],
  }
]

我想找到像这样具有此类别的产品。 我已尝试过:

Product.find({ categories:  mongoose.Types.ObjectId('5052843e023273693300010a')})
Product.find({ categories:  mongoose.mongo.BSONPure.ObjectID.fromString('5052843e023273693300010a')})
Product.find({ categories:  '5052843e023273693300010a'})
Product.find({ 'categories':  '5052843e023273693300010a'})
Product.find({ categories:  {$in: ['5052843e023273693300010a']}})
Product.find({ categories:  Schema.Types.ObjectId('5052843e023273693300010a')})
但是什么都不起作用。我可以使用以下方式通过id进行获取:_id: '5052843e023273693300013c'。
请注意,当插入产品时,类别ID被添加为字符串(这意味着我只是分配了ID而不是类别对象,但这并不能解释为什么上述任何内容都不起作用 - 在转储中未引用,因此Mongo可能将其识别为对象ID。
类似的SO问题没有得到答案。
我正在使用最新的Mongoose(3个版本)和最近的Mongo、Node。
更新:
我可以使用CLI轻松获取:
db.products.find({ categories: '5052843e02327369330000fe' }); 

有趣的是,我可以通过在代码中使用不等于符号来获取它 - 哦?

Product.find({ categories: { $ne: '5052843e02327369330000fe' }})

我的架构如下:

var Product = new Schema({
    title: { type: String, required: true },
    slug: { type: String },
    summary: { type: String }, //browser title
    description: { type: String, required: false },
    excerpt: { type: String },    //for a list and also for the meta description
    publish: { type: Boolean },
    featured: { type: Boolean },
    unavailable: { type: Boolean },
    model: { type: String },
    google: { type: String },
    tags: { type: Array },
    categories:  [{ type: Schema.Types.ObjectId, ref: 'Category' }],
    manufacturer: { type: String },
    variations: { type: Array },
    prices: { type: Array },
    images: { type: Array },
    specs: { type: Array },
    modified: { type: Date, default: Date.now }
});
    
var Category = new Schema({
    title: { type: String, required: true },
    description: { type: String },
    parent: { type: Schema.Types.ObjectId, ref: 'Category' },
    images: { type: Array }
});
谢谢。

Product 模型的架构定义是什么? - JohnnyHK
2个回答

17

使用Mongoose,在某些情况下需要将字符串强制转换为ID。通常它会自动为您执行此操作,但在您的特定情况下,它不会。以下代码片段将获取包含传递ID的所有连接。

var mongoose = require('mongoose');
Node.find({ connections: mongoose.Types.ObjectId("535c5c1b8aa6dc5f021e8a98") }, function (err, results) { 
    console.log(results); 
});

2
mongoose.Types.ObjectId() 正是我想要的! - Ornithopter
我越来越频繁地遇到这个问题,而且很难确定它何时发生以及何时不会发生。我不确定是否在使用具有查询 { _id: { $in: [ … ] } } 的 Mongoose .update 中遇到了这个问题。已知哪些情况下会出现这种情况?有人知道为什么会发生吗? - Paul Shapiro
我使用 import * as mongoose from 'mongoose'; 导入了 Mongoose。 - Shailesh Bhokare

0
发生的情况是,Mongoose将您在Product.find调用中使用的任何值转换为ObjectId,因为这是模式中定义的categories的类型。但是,您尝试匹配的文档的categories值具有字符串类型而不是ObjectId,因此无法匹配。
为了使事情再次正常工作,您需要清理现有文档以匹配定义的模式。

我的文档怎么可能有字符串类型?模式不是应该确保在我创建文档时(类似于express表单中的product.categories = req.params.categories),将提供的字符串转换为对象ID吗?我肯定不需要在创建时进行强制转换吧? - cyberwombat
@Yashua 我认为你在这里的意思是:当产品被插入时,类别ID被添加为字符串。如果您始终具有指示ObjectId数组的模式,并且通过Mongoose进行了所有插入,则它们应该已经是集合中的ObjectIds。 - JohnnyHK
@Yashua 根据你的更新,如果 db.products.find({ categories: '5052843e02327369330000fe' }); 在 CLI 中返回了你的文档,则在这种情况下 categories 确实 包含一个字符串而不是 ObjectId。 - JohnnyHK
我想问的是,当我只有ID而没有相关对象时(例如我的类别是从产品编辑表单中的下拉列表中选择的),如何将这些ID从表单插入为对象ID。这就是我所说的插入为字符串的意思。我现在发现的问题是,有时我的查询有效,这绝对表明了存储方式的波动-只是不确定如何保证正确的插入。我会做一些像var p = new Product; p.categories = req.params.categories(一个cat ID的post数组),然后p.save的操作。 - cyberwombat
@Yashua 将p.categories设置为ObjectId的字符串表示形式数组,然后调用p.save()应该可以正常工作。我刚刚进行了测试,保存在“categories”中的值是ObjectIds,不是字符串。 - JohnnyHK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接