Динамически создавать коллекцию с помощью Mongoose
Я хочу дать пользователям возможность создавать коллекции в моем приложении Node. Я действительно только видел пример жесткого кодирования в коллекциях с мангуста. Кто-нибудь знает, можно ли создавать коллекции динамически с mongoose? Если бы такой пример был бы очень полезен.
В основном я хочу иметь возможность хранить данные для разных "событий" в разных коллекциях.
т.е.
Мероприятия:
event1,
event2,
...
eventN
Пользователи могут создавать собственное пользовательское событие и хранить данные в этой коллекции. В конце каждого события могут быть сотни/тысячи строк. Я хотел бы предоставить пользователям возможность выполнять операции CRUD в своих событиях. Вместо хранения в одной большой коллекции я хотел бы хранить данные каждого события в другой коллекции.
У меня нет примера того, что я пробовал, так как я создал только "жестко закодированные" коллекции с мангуста. Я даже не уверен, что могу создать новую коллекцию в 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');
});
Выше работает отлично, если я жестко кодирую "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);
Вы можете это сделать?
Ответы
Ответ 1
Из mongo docs здесь: моделирование данных
В некоторых ситуациях вы можете хранить информацию в несколько коллекций, а не в одной коллекции.
Рассмотрим примеры журналов коллекции, в которых хранятся документы журнала для различные среды и приложения. Коллекция журналов содержит документы следующего вида:
{log: "dev", ts:..., info:...} {log: "debug", ts:..., info:...}
Если общее количество документов невелико, вы можете группировать документы в коллекция по типу. Для журналов рассмотрим возможность сохранения отдельного журнала коллекций, таких как logs.dev и logs.debug. Коллекция logs.dev будет содержать только документы, связанные с средой dev.
Как правило, наличие большого количества коллекций не имеет значительных и дает очень хорошую производительность. отчетливый коллекции очень важны для пакетной обработки с высокой пропускной способностью.
Ответ 2
Я считаю, что это ужасная идея для реализации, но вопрос заслуживает ответа. Вам нужно определить схему с динамическим именем, которая позволяет в ней вводить информацию типа "Любой". Функция для этого может быть немного похожа на эту функцию:
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];
}
Теперь вы можете создавать модели, которые позволяют получать информацию без каких-либо ограничений, включая имя. Я собираюсь предположить объект, определенный таким образом, {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);
}
});
Запросы очень похожи, выберите модель и выполните запрос:
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.
});
Вам нужно будет реализовать код для защиты ваших запросов. Вы не хотите, чтобы пользователь взорвал ваш db.
Ответ 3
Скажем, у меня 20 разных событий. Каждое событие имеет 1 миллион записей... Таким образом, если это все в одной коллекции, мне придется фильтровать коллекцию по событию для каждого CRUD-операции.
Я предлагаю вам хранить все события в одной коллекции, особенно если имена событий зависят от кода клиента и, следовательно, могут быть изменены. Вместо этого укажите имя и ссылку на пользователя.
mongoose.Schema({
name: { type: String, index: true },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', index: true }
});
Кроме того, я думаю, что вы столкнулись с проблемой немного назад (но я могу ошибаться). Вы находите события в контексте пользователя или находите пользователей в контексте имени события? У меня такое ощущение, что это первое, и вы должны разделить на ссылку пользователя, а не имя события в первую очередь.
Если вам не нужно находить все события для пользователя и просто нужно иметь дело с именем пользователя и события вместе, вы можете пойти с составным индексом:
schema.index({ user: 1, name: 1 });
Если вы имеете дело с миллионами документов, обязательно отключите автоматический индекс:
schema.set('autoIndex', false);
В этом сообщении есть интересные материалы об именах коллекций и использовании конкретной схемы:
Как получить доступ к существующей коллекции с помощью Mongoose?
Ответ 4
Вы можете попробовать следующее:
var createDB = function(name) {
var connection = mongoose.createConnection(
'mongodb://localhost:27017/' + name);
connection.on('open', function() {
connection.db.collectionNames(function(error) {
if (error) {
return console.log("error", error)
}
});
});
connection.on('error', function(error) {
return console.log("error", error)
});
}