NodeJS Mongo - Mongoose - 动态集合名称
Posted
技术标签:
【中文标题】NodeJS Mongo - Mongoose - 动态集合名称【英文标题】:NodeJS Mongo - Mongoose - Dynamic collection name 【发布时间】: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 以任何方式实现,以使读写都按预期工作?
【问题讨论】:
【参考方案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 开销似乎都不会增加太多。
【讨论】:
以上是关于NodeJS Mongo - Mongoose - 动态集合名称的主要内容,如果未能解决你的问题,请参考以下文章
通过Mongoose(Node JS)在Mongo DB中插入没有JSON模式的JSON对象