【问题标题】:NodeJS Mongo - Mongoose - Dynamic collection nameNodeJS Mongo - Mongoose - 动态集合名称
【发布时间】:2013-07-22 10:29:37
【问题描述】:

所以,我想创建一个基于客户端的分区模式,我将集合名称设置为 function(),我的伪代码是这样的:

var mongoose = require('mongoose'),
  Schema = mongoose.Schema,

var ConvForUserSchema = new Schema({
  user_id: Number,
  conv_hash: String,
  archived: Boolean,
  unread: Boolean
}, function CollectionName() {
  return (this.user_id % 10000);
});

这是否可以通过 moongose 以任何方式实现,以使读写都按预期工作?

【问题讨论】:

    标签: node.js mongodb mongoose nosql


    【解决方案1】:
    To Create a dynamic collection follow the below steps,
    
    const mongoose = require('mongoose');
    function createCompanyDynamicSchema(prefix) {
        let collectionName = prefix + '_company';
        companySchema = new mongoose.Schema(
            {
                name: { type: String },
                enabled: { type: Number, default: 1 },
            },
            { timestamps: true },
            { versionKey: false },
            { strict: false }
        );
        collectionName = mongoose.model(collectionName, companySchema);
        return collectionName;
    }
    
    module.exports = { createCompanyDynamicSchema };
    
    To call this method from any file, 
    
    let companySchema = require('./schema');
    
    _this.createCompany = function () {
        return new Promise(async (resolve, reject) => {
            let companyCollection = companySchema.createCompanyDynamicSchema('IO');
            let addr = new companyCollection({ first_name: 'test' });
            addr.save();
        });
    };
    
    
    To query from dynamically created collection,
    
    _this.getCompany = function () {
        return new Promise(async (resolve, reject) => {
            let companyCollection = companySchema.createCompanyDynamicSchema('IO');
            let data = await companyCollection.model('IO_users').find();
            console.log(data);
        });
    };
    

    【讨论】:

      【解决方案2】:

      我正在添加 Javier Gomez 的答案,以解决 Exis Zang 的“OverwriteModelError:一旦编译后无法覆盖 xxx 模型”问题。 Schema 模型文件可以存储基于 Singleton 模式的动态模型数组。如果该模型已经存在,则返回它,否则使用 new 创建它,存储并返回它:

      var mongoose  =  require('mongoose');
      var Schema  =  mongoose.Schema;
      
      const Addresses = {}
      
      // our schema 
      function DynamicSchema(prefix){
          var addressSchema = new Schema({
              dir : {type : String, required : true},    //los 2 nombres delimitados por coma (,) ej. Alberto,Andres
              city : {type : String, required: true},   //la misma estructura que para los nombres ej. Acosta, Arteta 
              postal : {type : Number, required : true},
              _home_type : {type : Schema.Types.ObjectId, required : true, ref : prefix + '.home_type'},
              state : {type : String, required : true},
              telefono : String,
              registered : {type : Date, default: Date.now }
          });
          return mongoose.model(prefix + '.address', addressSchema);
      }
      
      // this function will store the model in the Addresses object
      // on subsequent calls, if it exists, it will return it from the array
      function getAddressModel(prefix) {
        if (!Addresses[prefix]) {
          Addresses[prefix] =  new DynamicSchema(prefix)
        }
        return Addresses[prefix]
      }
      
      //now we export getAddressModel function
      module.exports = getAddressModel;
      

      【讨论】:

        【解决方案3】:

        使用函数动态获取模型。

        /* 
         * Define Schemas as you used to 
         */
        const ConvForUserSchema = new Schema({
            user_id: Number,
            conv_hash: String,
            archived: Boolean,
            unread: Boolean
        },{
            versionKey : false,
            strict: false
        });
        
        /*
         * Define the dynamic function
         */
        const models = {};
        const getModel = (collectionName) => {
            if( !(collectionName in models) ){
                models[collectionName] = connection.model(
                    collectionName, ConvForUserSchema, collectionName
                );
            }
            return models[collectionName];
        };
        

        然后使用函数得到动态模型

        const result = getModel("YourCollectionName").findOne({})
        

        【讨论】:

          【解决方案4】:


          您好,您只需要使用您的动态名称声明模式模型,如下所示:

          var mongoose  =  require('mongoose');
          var Schema  =  mongoose.Schema;
          
          // our schema 
          
          function dynamicSchema(prefix){
              var addressSchema = new Schema({
                  dir : {type : String, required : true},    //los 2 nombres delimitados por coma (,) ej. Alberto,Andres
                  city : {type : String, required: true},   //la misma estructura que para los nombres ej. Acosta, Arteta 
                  postal : {type : Number, required : true},
                  _home_type : {type : Schema.Types.ObjectId, required : true, ref : prefix + '.home_type'},
                  state : {type : String, required : true},
                  telefono : String,
                  registered : {type : Date, default: Date.now }
              });
              return mongoose.model(prefix + '.address', addressSchema);
          }
          
          //no we export dynamicSchema function
          module.exports = dynamicSchema;
          

          所以在你的代码中任何你可以做到的地方:

          var userAdress = require('address.js')(id_user);
          var usrAdrs1 = new userAddress({...});
              userAdrs1.save();
          

          现在转到您的 mongo shell 和列表集合(使用 mydb 然后显示集合),您将看到带有 uid 前缀的地址的新集合。这样mongoose会为每个不同的用户uid创建一个新的收集地址。

          【讨论】:

          • 我真的很喜欢这个解决方案,但我面临两种错误。首先,对于外键人口,似乎无法启动集合(因为 FK 被包裹在一个闭包中)而且OverwriteModelError: Cannot overwrite xxx model once compiled.
          【解决方案5】:

          已实现:

          //Require Mongoose
          const mongoose = require('mongoose');
          const moment = require('moment');
          
          //Define a schema
          const Schema = mongoose.Schema;
          
          const EntranceModelSchema = new Schema({
              name: String,
              birthday: Date,
              gender: String,
              phoneNumber: {type: String, require: true},
              email: String,
              address: String,
              addressReference: String,
              addressLatitude: {type: Number, require: true},
              addressLongitude: {type: Number, require: true},
              vehicleReference: String,
              date: Date
          });
          
          //Export function to create "SomeModel" model class
          module.exports = function(){
              let dateSuffix = moment().format('MMMDoYYYY');
              const collectionName = `Entrance${dateSuffix}`;
              return mongoose.model(collectionName, EntranceModelSchema);
          };
          

          【讨论】:

            【解决方案6】:

            Gomosoft 的解决方案有效。它需要一些修改,但这个想法很有效。 上述解决方案仅在第一次时有效。如果您尝试向同一个集合发送第二个请求,它会因为尝试覆盖已定义的模型而引发错误。所以我不得不对其进行如下调整:

            var Rating      = require('./app/models/rating');
            var myRating;
            
            router.route('/ratings/:user_id')
            .post(function(req,res){
            
                var user_id         = req.params.user_id;
                if(myRating == undefined){
                    myRating        = Rating(user_id);  
                }
            
                ...
            
                rating.save(...);
            });
            

            因为我正在检查 myRating 是否未定义,所以它只会创建一次此引用。所以不会出现错误。 希望这会有所帮助。

            【讨论】:

            • 我认为这很难与 2 个单独的 user_id 一起使用。
            【解决方案7】:

            集合名称逻辑在整个 Moongose 代码库中都进行了硬编码,因此无法按照现在的情况进行客户端分区。

            我的解决方案是直接使用 mongo 驱动程序 -

            https://github.com/mongodb/node-mongodb-native

            事实证明这很好,直接与驱动程序合作的灵活性允许所有需要的东西,而且在任何情况下,Moongose 开销似乎都不会增加太多。

            【讨论】:

              猜你喜欢
              • 2014-09-22
              • 1970-01-01
              • 2020-08-24
              • 2020-11-11
              • 2011-11-21
              • 1970-01-01
              • 2021-03-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多