阻止Mongoose为子文档数组项创建_id属性

325

如果您有子文档数组,Mongoose 会自动为每个子文档创建 ID。例如:

{
    _id: "mainId"
    subDocArray: [
      {
        _id: "unwantedId",
        field: "value"
      },
      {
        _id: "unwantedId",
        field: "value"
      }
    ]
}

有没有办法告诉Mongoose不要为数组中的对象创建id?

7个回答

431

很简单,你可以在子架构中定义它:

var mongoose = require("mongoose");

var subSchema = mongoose.Schema({
    // your subschema content
}, { _id : false });

var schema = mongoose.Schema({
    // schema content
    subSchemaCollection : [subSchema]
});

var model = mongoose.model('tablename', schema);

2
这会跳过子模式集合中的 _id 字段吗?还是只在将子模式用作子文档项数组嵌入的情况下才会跳过?我之所以问这个问题,是因为我今天在 Stack Overflow 上提出了类似的问题 - Web User
1
我使用了两个级别的嵌套子架构集合。换句话说,我有一个类似于你示例的SubSchema 集合。在此之内,我使用另一个不同的子模式集合。我只希望第一级子架构模型实例不使用id,但第二级(嵌套)子架构模型实例需要具有ids。当我使用您的解决方案即指定 { _id:false } 时,两个级别的子架构都没有ID。有什么方法可以解决这个问题? - Web User
1
你尝试过为第三层设置 { _id : true } 吗? - throrin19
1
昨天我尝试了更改以下内容:let studentSchema = new Schema({ studentId: { type: ObjectId, ref: Student.modelName }, performance: [performanceSchema] }, { _id: false }); 到这个:let studentSchema = new Schema({ _id: false, id: false, studentId: { type: ObjectId, ref: Student.modelName }, performance: [performanceSchema] }); 这样做停止了在 studentSchema 上创建 _id,但保留了子文档 performance 数组中对象的 _id 创建。不确定是否需要同时使用 _id: falseid: false - Web User

211
您可以创建没有模式并避免 _id 的子文档。只需在子文档声明中添加 _id: false 即可。
var schema = new mongoose.Schema({
   field1: {
      type: String
   },
   subdocArray: [{
      _id: false,
      field: { type: String }
   }]
});

这将防止在您的子文档中创建一个_id字段。

在Mongoose v5.9.10中测试过


58

此外,如果您使用对象文字语法指定子模式,也可以只添加_id: false来禁止它。

{
   sub: {
      property1: String,
      property2: String,
      _id: false
   }
}

32

我正在使用mongoose 4.6.3,我所需要做的就是在模式中添加_id:false,不需要创建子模式。

{
    _id: ObjectId
    subDocArray: [
      {
        _id: false,
        field: "String"
      }
    ]
}

有没有一种方法可以使整个集合中的元素唯一? - Saitama
可能不是用这种方法,但你可以试试看。_id 是一个字段而不是一个约束。 - jemiloii
如果在创建子文档的时候,我明确地将_id = mongoose.Types.ObjectId()进行赋值,那么该_id是否会在整个集合中唯一? - Saitama
只需打开一个新的 Stack Overflow,这样你就可以一次得到许多人的答案~ - jemiloii

6
您可以使用其中任意一个。
var subSchema = mongoose.Schema({
//subschema fields    

},{ _id : false });

或者
var subSchema = mongoose.Schema({
//subschema content
_id : false    

});

在使用第二个选项之前,请检查您的mongoose版本。


4
任何正在寻找装饰器解决方案的人,都可以参考此NestJS示例。
@Schema({_id: false})
export class MySubDocument {
    @Prop()
    id: string;
}

以下是Mongoose Schema Type定义中有关id_id的一些额外信息:
/**
* Mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field
* cast to a string, or in the case of ObjectIds, its hexString.
*/
id?: boolean;

/**
* Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema
* constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you
* don't want an _id added to your schema at all, you may disable it using this option.
*/
_id?: boolean;

4

如果你想将一个带有_id的预定义模式作为子文档(没有_id)使用,理论上可以按照以下方式进行:

const sourceSchema = mongoose.Schema({
    key : value
})
const subSourceSchema = sourceSchema.clone().set('_id',false);

但那对我不起作用。所以我加了这个:

delete subSourceSchema.paths._id;

现在我可以在父文档中包含 subSourceSchema 而不需要 _id 了。 我不确定这是否是正确的做法,但它能工作。


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