Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS Mongo - Mongoose - Dynamic collection name

So, I want to create a client side based paritioning schema, where I set the collection name as function(), my pseudo code is something like that:

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

Is this in any way possible through moongose such that both read and writes will work as expected?

like image 864
JAR.JAR.beans Avatar asked Jul 23 '13 11:07

JAR.JAR.beans


4 Answers


Hello you just need to declare schema model with your dinamically name, like this:

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;

so in your code anywhere you can do this:

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

Now go to your mongo shell & list collections (use mydb then show collections), you will see a new collection for address with uid prefix. In this way mongoose will create a new one collection address for each different user uid.

like image 193
Javier Gomez Avatar answered Oct 11 '22 17:10

Javier Gomez


Use the function to get the model dynamically.

/* 
 * 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];
};

Then get the dynamic model using the function

const result = getModel("YourCollectionName").findOne({})
like image 25
Manvel Avatar answered Oct 11 '22 18:10

Manvel


Collection name logic is hard coded all over the Moongose codebase such that client side partitioning is just not possible as things stands now.

My solution was to work directly with the mongo driver -

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

This proved great, the flexibility working with the driver directly allows for everything required and the Moongose overhead does not seem to add much in any case.

like image 6
JAR.JAR.beans Avatar answered Oct 11 '22 17:10

JAR.JAR.beans


Implemented:

//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);
};
like image 3
alacret Avatar answered Oct 11 '22 18:10

alacret