如何在猫鼬中将 ObjectId 设置为数据类型

Posted

技术标签:

【中文标题】如何在猫鼬中将 ObjectId 设置为数据类型【英文标题】:How to set ObjectId as a data type in mongoose 【发布时间】:2011-12-28 01:13:42 【问题描述】:

在 mongoHQ 和 mongoose 上使用 node.js、mongodb。我正在为类别设置架构。我想使用文档 ObjectId 作为我的 categoryId。

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Category = new Schema(
    categoryId  : ObjectId,
    title       : String,
    sortIndex   : String
);

然后我跑

var Category = mongoose.model('Schema_Category');
var category = new Category();
category.title = "Bicycles";
category.sortIndex = "3";

category.save(function(err) 
  if (err)  throw err; 
  console.log('saved');
  mongoose.disconnect();     
);

请注意,我没有为 categoryId 提供值。我假设猫鼬将使用模式来生成它,但文档具有通常的“_id”而不是“categoryId”。我做错了什么?

【问题讨论】:

【参考方案1】:

与传统的 RBDM 不同,mongoDB 不允许您将任何随机字段定义为主键,所有标准文档都必须存在 _id 字段。

因此,创建单独的 uuid 字段没有意义。

在 mongoose 中,ObjectId 类型不是用来创建新的 uuid,而是主要用于引用其他文档。

这是一个例子:

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Product = new Schema(
    categoryId  : ObjectId, // a product references a category _id with type ObjectId
    title       : String,
    price       : Number
);

如您所见,使用 ObjectId 填充 categoryId 没有多大意义。

但是,如果您确实想要一个命名良好的 uuid 字段,mongoose 提供了允许您代理(引用)字段的虚拟属性。

检查一下:

var mongoose = require('mongoose');

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
var Schema_Category = new Schema(
    title       : String,
    sortIndex   : String
);

Schema_Category.virtual('categoryId').get(function() 
    return this._id;
);

所以现在,每当您调用 category.categoryId 时,mongoose 只会返回 _id。

你也可以创建一个“set”方法来设置虚拟属性,查看this link 了解更多信息

【讨论】:

设置虚拟属性后,我尝试了:db.cats.find(categoryId: ObjectId("the id")) 但得到了空结果。当我使用 db.cats.find(_id: ObjectId("the id")) 我确实得到了一个文档。所以看起来虚拟属性不能用于搜索。我认为,如果可以使用清晰的名称引用每个 ID,而不是使用 _id 来表示所有内容,那么管理代码会更容易。只是一个想法......【参考方案2】:

我一直在为问题标题寻找不同的答案,所以也许其他人也会。

要将 type 设置为 ObjectId(例如,您可以将 author 称为 book 的作者),您可以这样做:

const Book = mongoose.model('Book', 
  author: 
    type: mongoose.Schema.Types.ObjectId, // here you set the author ID
                                          // from the Author colection, 
                                          // so you can reference it
    required: true
  ,
  title: 
    type: String,
    required: true
  
);

【讨论】:

【参考方案3】:

我使用 ObjectId 的解决方案

// usermodel.js

const mongoose = require('mongoose')
const Schema = mongoose.Schema
const ObjectId = Schema.Types.ObjectId


let UserSchema = new Schema(
   username: 
     type: String
   ,
   events: [
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   ]
)

UserSchema.set('autoIndex', true)

module.exports = mongoose.model('User', UserSchema)

使用猫鼬的populate方法

// controller.js

const mongoose = require('mongoose')
const User = require('./usermodel.js')

let query = User.findOne( name: "Person" )

query.exec((err, user) => 
  if (err) 
     console.log(err)
  

  user.events = events
  // user.events is now an array of events
)

【讨论】:

如何在事件字段中添加默认值?【参考方案4】:

@dex 提供的解决方案对我有用。但我想添加一些对我也有用的东西:使用

let UserSchema = new Schema(
   username: 
     type: String
   ,
   events: [
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   ]
)

如果您要创建的是数组引用。但是,如果您想要的是一个对象引用,我认为您可能正在寻找它,请从 value 属性中删除括号,如下所示:

let UserSchema = new Schema(
   username: 
     type: String
   ,
   events: 
     type: ObjectId,
     ref: 'Event' // Reference to some EventSchema
   
)

看好2个sn-ps。第二种情况,key events 的 value prop 在对象 def 上没有括号。

【讨论】:

【参考方案5】:

可以直接定义ObjectId

var Schema = new mongoose.Schema( categoryId : mongoose.Schema.Types.ObjectId, 标题:字符串, 排序索引:字符串 )

注意:你需要导入猫鼬模块

【讨论】:

以上是关于如何在猫鼬中将 ObjectId 设置为数据类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在猫鼬中分配一个objectid数组

如何在猫鼬节点js中为朋友创建模式

使用种子字符串在猫鼬中创建 ObjectId

使用种子字符串在猫鼬中创建 ObjectId

如何在猫鼬中更新嵌套数组值

通过在猫鼬中填充匹配结果来查找文档