使用Mongoose动态创建集合

los*_*ion 22 mongoose node.js

我想让用户能够在我的Node应用程序中创建集合.我真的只看到了用mongoose收集硬编码的例子.任何人都知道是否可以使用mongoose动态创建集合?如果是这样,一个例子会非常有帮助.

基本上我希望能够在不同的集合中存储不同"事件"的数据.

IE事件:event1,event2,... eventN

用户可以在该集合中创建自己的自定义事件并存储数据.最后,每个事件可能有数百/数千行.我想让用户能够对他们的事件执行CRUD操作.我想将每个事件数据存储在不同的集合中,而不是存储在一个大集合中.

我真的没有一个我尝试过的例子,因为我只使用mongoose创建了"硬编码"集合.我甚至不确定我是否可以根据用户请求在mongoose中创建一个动态的新集合.

var mongoose = require('mongoose');
mongoose.connect('localhost', 'events');

var schema = mongoose.Schema({ name: 'string' });
var Event1 = mongoose.model('Event1', schema);

var event1= new Event1({ name: 'something' });
event1.save(function (err) {
  if (err) // ...
  console.log('meow');
});
Run Code Online (Sandbox Code Playgroud)

如果我将'Event1'硬编码为集合,则上述工作非常有用.不确定我是否创建了动态集合.

var mongoose = require('mongoose');
mongoose.connect('localhost', 'events');

...

var userDefinedEvent = //get this from a client side request
...

var schema = mongoose.Schema({ name: 'string' });
var userDefinedEvent = mongoose.model(userDefinedEvent, schema);
Run Code Online (Sandbox Code Playgroud)

你能做到吗?

Roe*_*den 19

我认为这是一个可怕的想法,但一个问题值得回答.您需要定义一个动态名称的模式,该模式允许其中包含"任何"类型的信息.执行此操作的功能可能与此功能有点类似:

var establishedModels = {};
function createModelForName(name) {
    if (!(name in establishedModels)) {
        var Any = new Schema({ any: Schema.Types.Mixed });
        establishedModels[name] = mongoose.model(name, Any);
    }
    return establishedModels[name];
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以创建允许信息的模型,而不受任何限制,包括名称.我将假设一个像这样定义的对象{name: 'hello', content: {x: 1}},由'用户'提供.为了保存这个,我可以运行以下代码:

var stuff = {name: 'hello', content: {x: 1}}; // Define info.
var Model = createModelForName(name); // Create the model.
var model = Model(stuff.content); // Create a model instance.
model.save(function (err) { // Save
    if (err) {
        console.log(err);
    }
});
Run Code Online (Sandbox Code Playgroud)

查询非常相似,获取模型然后执行查询:

var stuff = {name: 'hello', query: {x: {'$gt': 0}}}; // Define info.
var Model = createModelForName(name); // Create the model.
model.find(stuff.query, function (err, entries) {
    // Do something with the matched entries.
});
Run Code Online (Sandbox Code Playgroud)

您必须实现代码以保护您的查询.您不希望用户炸毁您的数据库.

  • 只做一个索引?这就是为什么我们有指数.而且,提出替代方案的问题不是答案的答案.它是回答提出的问题. (4认同)

los*_*ion 6

来自mongo docs:数据建模

在某些情况下,您可能选择将信息存储在多个集合中,而不是存储在单个集合中.

考虑一个样本集合日志,它存储各种环境和应用程序的日志文档.日志集合包含以下格式的文档:

{log:"dev",ts:...,info:...} {log:"debug",ts:...,info:...}

如果文档总数较低,您可以按类型将文档分组.对于日志,请考虑维护不同的日志集合,例如logs.dev和logs.debug.logs.dev集合仅包含与dev环境相关的文档.

通常,具有大量集合没有显着的性能损失并且导致非常好的性能.不同的集合对于高吞吐量批处理非常重要.


AJc*_*dez 5

假设我有 20 个不同的事件。每个事件都有 100 万个条目……因此,如果这都在一个集合中,我将不得不为每个 CRUD 操作按事件过滤集合。

我建议您将所有事件保存在同一个集合中,特别是如果事件名称依赖于客户端代码,因此可能会发生变化。相反,索引名称和用户引用。

mongoose.Schema({
  name: { type: String, index: true },
  user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', index: true } 
});
Run Code Online (Sandbox Code Playgroud)

此外,我认为您的问题有点倒退(但我可能会弄错)。您是在用户上下文中查找事件,还是在事件名称上下文中查找用户?我有一种感觉是前者,您应该首先根据用户引用而不是事件名称进行分区。

如果您不需要查找用户的所有事件而只需要一起处理用户和事件名称,您可以使用复合索引:

schema.index({ user: 1, name: 1 });
Run Code Online (Sandbox Code Playgroud)

如果您正在处理数百万个文档,请确保关闭自动索引:

schema.set('autoIndex', false);
Run Code Online (Sandbox Code Playgroud)

这篇文章有关于命名集合和使用特定模式的有趣内容:

如何使用 Mongoose 访问预先存在的集合?