簡體   English   中英

如何在 MongoDB/Mongoose 中動態添加模式

[英]How to add Schema Dynamically in MongoDB/Mongoose

我想創建一個由用戶定義的數據庫,每個用戶都可以擁有自己的數據庫風格。 所以我使用了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);

在上述情況下,我希望設置由用戶定義,例如,

{
    "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]
        }
    }
}

所以請告訴我,我怎樣才能讓用戶定義模式的類型?

strict: true並不意味着您可以將任何內容傳遞給settings字段。

這意味着您的架構格式是動態的 - 您可以在架構中未定義的文檔中有意外的字段名稱。


回答您的問題:

似乎您想要子文檔,讓我們創建另一個架構並將其附加為類型:

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);



但要獲得更大的靈活性,避免產生大的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);

將其創建為:

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});
  }
});

並根據請求時間將其作為:

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});
  }
});

將您的設置字段定義為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);

保存文檔時:

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.'});}
   });

});

以防萬一有人在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM