Créer une collection dynamique avec Mongoose
je veux donner aux utilisateurs la possibilité de créer des collections dans mon application Node. Je n'ai vraiment vu exemple de codage dur dans les collections avec mongoose. Quelqu'un sait s'il est possible de créer des collections dynamiquement avec mongoose? Si donc un exemple serait très utile.
Fondamentalement, je veux être capable de stocker des données pour les différents "événements" dans différentes collections.
I. E. Événement: event1, événement2, ... eventN
les utilisateurs peuvent y créer leurs propres et stocker des données dans cette collection. En fin de compte, chaque événement pourrait avoir des centaines/milliers de lignes. Je voudrais donner aux utilisateurs la possibilité d'effectuer des opérations CRUD sur leurs événements. Plutôt que de stocker dans une grande collection, j'aimerais stocker les données de chaque événement dans une collection différente.
Je n'ai pas vraiment d'exemple de ce que j'ai essayé car je n'ai créé que des collections 'codées dur' avec mongoose. Je ne suis même pas sûr que je peux créer une nouvelle collection à mongoose qui est dynamique basée sur une demande de l'utilisateur.
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');
});
ci-dessus fonctionne très bien si je code dur 'Event1' comme une collection. Je ne suis pas sûr de créer une collection dynamique.
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);
Pouvez-vous faire?
4 réponses
je crois que c'est une très mauvaise idée à mettre en oeuvre, mais une question mérite une réponse. Vous devez définir un schéma avec un nom dynamique qui permet des informations de "N'importe quel" type. Une fonction peut-être un peu similaire à cette fonction:
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];
}
Maintenant vous pouvez créer des modèles qui permettent l'information sans aucune restriction, y compris le nom. Je vais supposer un objet défini comme ceci, {name: 'hello', content: {x: 1}}
, qui est fourni par l'utilisateur. Pour sauver ceci, je peux courir le code suivant:
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);
}
});
les Requêtes sont très similaires, de récupérer le modèle, puis de faire une requête:
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.
});
vous devrez implémenter du code pour protéger vos requêtes. Vous ne voulez pas que l'utilisateur fasse exploser votre base de données.
à Partir de mongo docs ici: modélisation de données
Dans certaines situations, vous pouvez choisir de stocker des informations dans plusieurs collections plutôt que dans une seule collection.
envisager des journaux de collecte d'échantillons qui stockent les documents de journaux pour Divers Environnement et applications. La collection de journaux contient les documents de la forme suivante:
{ journal: "dev", ts: ..., info. :.. } { journal: "debug", ts: ..., info. :..}
si le nombre total de documents est faible, vous pouvez grouper les documents en la collecte par type. Pour les grumes, envisagez de conserver des grumes distinctes. les collections, comme les journaux.dev et les journaux.débogage. Journal.collection dev contient les documents relatifs à l'environnement de dev.
Généralement, d'avoir un grand nombre de collections n'est pas significative les performances et les résultats dans de très bonnes performances. Distinct les collections sont très importantes pour les lots à haut rendement traitement.
disons que j'ai 20 événements différents. Chaque événement a 1 million d'entrées... En tant que tel, si tout cela fait partie d'une seule collection, je devrai filtrer la collection par événement pour chaque opération CRUD.
je vous suggérerais de garder tous les événements dans la même collection, surtout si les noms d'événements dépendent du code client et sont donc sujets à changement. À la place, indexez le nom et la référence de l'utilisateur.
mongoose.Schema({
name: { type: String, index: true },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', index: true }
});
en outre, je pense que vous avez abordé le problème un peu à l'envers (mais je peut-être à tort). Trouvez-vous les événements dans le contexte d'un utilisateur, ou la recherche d'utilisateurs dans le contexte d'un nom d'événement? J'ai l'impression que c'est le premier, et vous devriez partager sur la référence de l'Utilisateur, pas le nom de l'événement en premier lieu.
Si vous n'avez pas besoin de trouver tous les événements pour un utilisateur, il suffit de traiter avec l'utilisateur et le nom de l'événement ensemble, vous pourriez aller avec un index composé:
schema.index({ user: 1, name: 1 });
Si vous avez affaire à des millions de documents, assurez-vous de désactiver l'auto index:
schema.set('autoIndex', false);
Ce post a des choses intéressantes sur l'attribution de noms des collections et à l'aide d'un schéma:
comment accéder à une collection préexistante avec Mongoose?
Vous pouvez essayer la commande suivante:
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)
});
}
Il est important que vous obteniez les noms des collections avec connexion.DB.collectionNames, sinon la base de données ne sera pas créée.