NodeJS Mongo - Mongoose - 动态集合名称

时间:2013-07-23 11:19:55

标签: node.js mongodb mongoose nosql

所以,我想创建一个基于客户端的分区模式,我将集合名称设置为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实现,以便读取和写入都能按预期工作?

7 个答案:

答案 0 :(得分:4)


你好,你只需要用你的dinamically名称声明架构模型,如下所示:


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


// our schema 


function dinamycSchema(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 dinaymicSchema function

module.exports = dinamycModel;

所以在你的代码中你可以做到这一点:

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


现在去你的mongo shell&列表集合(使用mydb然后显示集合),您将看到一个带有uid前缀的地址的新集合。通过这种方式,mongoose将为每个不同的用户uid创建一个新的集合地址。

干杯...

答案 1 :(得分:2)

集合名称逻辑在整个Moongose代码库中都是硬编码的,因此客户端分区现在就不可能了。

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

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

事实证明这很好,与驱动程序一起使用的灵活性直接允许所需的一切,并且Moongose开销在任何情况下似乎都没有增加太多。

答案 2 :(得分:1)

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 是否未定义,所以它只会创建此引用一次。所以不会发生错误。 希望这会有所帮助。

答案 3 :(得分:1)

我的建议是动态创建模型:

let dynamicModels = {};
const ConvForUserSchema = new Schema({
    user_id: Number,
    conv_hash: String,
    archived: Boolean,
    unread: Boolean
},{
    versionKey : false,
    strict: false
});

const dynamicModel = (collectionName) => {
    if( !(collectionName in dynamicModels) ){
        dynamicModels[collectionName] = connection.model(collectionName, ConvForUserSchema, collectionName);
    }
    return dynamicModels[collectionName];
};

然后您就可以使用

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

答案 4 :(得分:0)

实现:

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

答案 5 :(得分:0)

我正在添加 Javier Gomez 的答案,以解决 Exis Zang 的“OverwriteModelError:无法覆盖 xxx 模型一旦编译”问题。 Schema 模型文件可以存储基于单例模式的动态模型数组。如果该模型已经存在,则返回它,否则使用 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;

答案 6 :(得分:0)

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