[英]How to add Schema Dynamically in MongoDB/Mongoose
I want to create a database thats defined by user, each user can have his own flavor of database.我想创建一个由用户定义的数据库,每个用户都可以拥有自己的数据库风格。 So i used strict: false
But Now the problem is I cant make the user define the type
of each schema under the model所以我使用了strict: false
但是现在的问题是我不能让用户定义模型下每个模式的type
const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
label: {
required: 'please enter label',
trim: true,
type: String
},
url: {
type: String,
trim: true,
},
settings: {} //User defined
}, {
timestamps: true, strict: false
});
module.exports = mongoose.model('test', testSchema);
In the above case, I want the setting to be defined by user like,在上述情况下,我希望设置由用户定义,例如,
{
"label": "About Us",
"url": "www.google.com",
"settings": {
"name": {
"type": "String", //Problem is Here, i can't send datatype directly
"required": true
},
"age": {
"type": "Number",
"required": true,
"enum": [10, 12]
}
}
}
So please tell help me, how can i make the user define the type of the schema?所以请告诉我,我怎样才能让用户定义模式的类型?
strict: true
does not mean You can pass anything to settings
field. strict: true
并不意味着您可以将任何内容传递给settings
字段。
It means Your schema format is dynamic - You can have unexpected field names in document that is not defined in schema.这意味着您的架构格式是动态的 - 您可以在架构中未定义的文档中有意外的字段名称。
Answer to Your issue:回答您的问题:
Seems like You want subdocument, let's make another schema and attach it as type:似乎您想要子文档,让我们创建另一个架构并将其附加为类型:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const types = Schema.Types;
const testSettingsSchema = new Schema({
name: {
type: types.String,
required: true
},
age: {
type: types.Number,
required: true
enum: [10, 12]
}
},
{
_id : false,
timestamps: false,
strict: false
});
const testSchema = new Schema({
label: {
required: 'please enter label',
trim: true,
type: types.String
},
url: {
type: types.String,
trim: true,
},
settings: {
type: testSettingsSchema,
required: true
}
},
{
timestamps: true,
strict: true
});
module.exports = mongoose.model('test', testSchema);
But to gain more flexibility and avoid creating big test
document (since user may push unpredictable big object), create another schema: testSettings
that points to test_settings
collection and make settings
field to be reference:但要获得更大的灵活性,避免产生大的test
文件(因为用户可以推动不可预知的大对象),创建另一个模式: testSettings
它指向test_settings
收集,并settings
字段设置为参考:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const types = Schema.Types;
const testSettingsSchema = new Schema({
name: {
type: types.Mixed
},
age: {
type: types.Mixed
}
},
{
collection: 'test_settings',
timestamps: false,
strict: false // tells to mongoose that schema may "grow"
});
mongoose.model('testSettings', testSettingsSchema);
const testSchema = new Schema({
label: {
required: 'please enter label',
trim: true,
type: types.String
},
url: {
type: types.String,
trim: true,
},
settings: {
type: types.ObjectId,
ref: 'testSettings'
default: null
}
},
{
collection: 'tests',
timestamps: true,
strict: true
});
module.exports = mongoose.model('test', testSchema);
create it as:将其创建为:
const Test = mongoose.model('test');
const TestSettings = mongoose.model('testSettings');
app.post('/tests', async (req, res) => {
try {
const testSettings = await TestSettings.create(req.body.settings);
const test = new Test(req.body);
test.settings = testSettings._id;
await test.save();
res.status(201).send({_id: test._id});
}
catch(error) {
res.status(500).send({message: error.message});
}
});
and on request time get it as:并根据请求时间将其作为:
const Test = mongoose.model('test');
app.get('/tests/:id', async (req, res) => {
try {
const test = await Test.findById(req.params.id)
.populate('settings')
.lean();
res.status(200).send(test);
}
catch(error) {
res.status(500).send({message: error.message});
}
});
define your setting field as Schema.Types.Mixed , so you can able to set any kind of fields inside it , like Number , String , Array , Date , Boolean
..etc将您的设置字段定义为Schema.Types.Mixed ,以便您可以在其中设置任何类型的字段,例如Number , String , Array , Date , Boolean
..etc
const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
label: {
required: 'please enter label',
trim: true,
type: String
},
url: {
type: String,
trim: true,
},
settings: {
type:Schema.Types.Mixed ,
default: {}
}
}, {
timestamps: true, strict: false
});
module.exports = mongoose.model('test', testSchema);
While saving the document :保存文档时:
app.post('/save',function(req,res){
var setting = {};
setting.age= req.body.age;
setting.name= req.body.name;
var test = new Test({
test.label: req.body.label;
test.url :req.body.url;
test.setting: setting
});
test.save(function(err){
if(err) {return res.json(err);}
else{ res.json({status:'success',message:'saved.'});}
});
});
Just in case someone is having this issue with NestJS and schemaFactory, that's how I solved it:以防万一有人在 NestJS 和 schemaFactory 上遇到这个问题,我就是这样解决的:
...
@Schema({ strict: false })
export class Content {}
@Schema()
export class Deadletter extends Document {
@Prop({type: Header})
header: Header;,
@Prop({type: Metadata})
_metadata?: Metadata;
@Prop({type: Content})
content: any;
}
export const deadLetterFullSchema = SchemaFactory.createForClass(Deadletter);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.