131 votes

Comment organiser une application node qui utilise sequelize ?

Je suis à la recherche d'un exemple d'application nodejs qui utilise l'ORM sequelize.

Ma principale préoccupation est qu'il semble pratiquement impossible de définir vos modèles dans des fichiers js distincts si ces modèles ont des relations complexes les uns avec les autres en raison des boucles de dépendance require(). Peut-être que les gens définissent tous leurs modèles dans un seul fichier qui est très très long ?

Je suis principalement intéressé par la façon dont les modèles sont définis et utilisés dans l'application. J'aimerais avoir la confirmation que ce que je fais par moi-même est la "bonne" façon de faire les choses.

3 votes

J'ai ajouté un exemple qui pourrait aider quelqu'un github.com/shaishab/sequelize-express-example

0 votes

J'ai écrit un article sur notre solution : medium.com/@ismayilkhayredinov/

129voto

user1778770 Points 532

La nouvelle

L'astuce dans ce cas n'est pas d'initialiser le modèle sur le fichier mais simplement de fournir les informations nécessaires à son initialisation et de laisser un module centralisé se charger de la configuration et de l'instanciation des modèles.

Donc les étapes sont :

  • Avoir plusieurs fichiers de modèle avec des données sur le modèle, comme les champs, les relations et les options.
  • Avoir un module singleton qui charge tous ces fichiers et configure toutes les classes et relations du modèle.
  • Configurez votre module singleton dans le fichier app.js.
  • Obtenir les classes du modèle à partir du module singleton no utiliser require sur vos fichiers de modèles, chargez les modèles à partir du singleton à la place.

La suite de l'histoire

Voici une description plus détaillée de cette solution avec le code source correspondant :

http://jeydotc.github.io/blog/2012/10/30/EXPRESS-WITH-SEQUELIZE.html

EDIT : C'est une très vieille réponse ! (lisez en bas pour l'info)

Il est vieux et limité à bien des égards !

  • Premier Comme @jinglesthula l'a mentionné dans les commentaires (et j'en ai fait l'expérience aussi), il y a des problèmes avec la nécessité de ces fichiers. C'est parce que require ne fonctionne pas de la même manière que readdirSync !

  • Deuxièmement - vous êtes très limité dans les relations - le code ne prévoit pas options à ces associations pour que vous soyez UNABLE pour créer belongsToMany comme il le faut through propriété. Vous pouvez faire les assocs les plus basiques.

  • Troisièmement - vous êtes très limité dans les relations avec les modèles ! Si vous lisez attentivement le code, vous verrez que relations est une fonction Objet au lieu d'un Array donc si vous voulez faire plus d'un associations du même type (comme avoir deux fois belongsTo ) - vous ne pouvez pas !

  • Quatrièmement - Vous n'avez pas besoin de ce truc de singleton. Chaque module dans nodejs est singleton par lui-même, donc tout ceci est assez complexe pour aucune raison.

Vous devriez voir la réponse de Farm ! (Le lien vers l'article est cassé, mais je vais le réparer avec cet échantillon officiel de sequelize : https://github.com/sequelize/express-example/blob/master/models/index.js - vous pouvez parcourir l'ensemble du projet pour vous faire une idée de ce qui se passe).

p.s. J'édite ce post car il est tellement upvoted que les gens ne verront même pas de nouvelles réponses (comme moi).

Editar: Je viens de changer le lien vers une copie du même message, mais dans une page Github.

0 votes

Aussi, j'avais l'impression que tous les require Les modules de node étaient en quelque sorte des singletons car le code qu'ils contiennent est exécuté une fois puis mis en cache, de sorte que la prochaine fois que vous en avez besoin, vous obtenez une référence d'objet en cache. N'est-ce pas là toute l'image ?

1 votes

@mkoryak, vous avez raison - tous les modules commonjs dans node sont effectivement des singletons, car la valeur retournée est mise en cache après la première exécution. nodejs.org/api/modules.html#modules_caching

2 votes

Ainsi, l'exemple pourrait être simplifié en supprimant la partie délicate du singleton et en mettant simplement module.exports = new OrmClass(). Je vais l'essayer, merci pour vos commentaires :)

96voto

Farm Points 635

SequelizeJS a un article sur leur site web qui résout ce problème.

Le lien est cassé, mais vous pouvez trouver l'exemple de projet fonctionnel. aquí et le parcourir. Voir la réponse éditée ci-dessus pour comprendre pourquoi c'est une meilleure solution.

Extrait de l'article :

  • modèles/index.js

    L'idée de ce fichier est de configurer une connexion à la base de données et de rassembler toutes les définitions de Modèle. Une fois que tout est en place, nous allons appeler la méthode associée sur chacun des Modèles. Cette méthode peut être utilisée pour associer le Modèle à d'autres.

          var fs        = require('fs')
            , path      = require('path')
            , Sequelize = require('sequelize')
            , lodash    = require('lodash')
            , sequelize = new Sequelize('sequelize_test', 'root', null)
            , db        = {} 
    
          fs.readdirSync(__dirname)
            .filter(function(file) {
              return (file.indexOf('.') !== 0) && (file !== 'index.js')
            })
            .forEach(function(file) {
              var model = sequelize.import(path.join(__dirname, file))
              db[model.name] = model
            })
    
          Object.keys(db).forEach(function(modelName) {
            if (db[modelName].options.hasOwnProperty('associate')) {
              db[modelName].options.associate(db)
            }
          })
    
          module.exports = lodash.extend({
            sequelize: sequelize,
            Sequelize: Sequelize
          }, db)

12 votes

C'est la façon dont Sequelize recommande de le faire. Je l'accepterais comme la réponse correcte.

0 votes

J'ai corrigé le lien cassé et ajouté une explication à la question sélectionnée pour expliquer pourquoi ce n'est pas correct :)

3 votes

C'est bien, mais vous ne pouvez pas utiliser un modèle à partir des méthodes d'instance d'un autre modèle, ou peut-être ai-je manqué quelque chose.

8voto

mvbl fst Points 2403

J'ai commencé à utiliser Sequelize dans une application Express.js. Assez rapidement, j'ai rencontré des problèmes de la nature de ceux que vous décrivez. Peut-être que je n'ai pas bien compris Sequelize, mais pour moi, faire des choses plus que simplement sélectionner dans une table n'était pas vraiment pratique. Et là où normalement vous utiliseriez select from two or more tables, ou une union en SQL pur, vous auriez à exécuter des requêtes séparées, et avec la nature async de Node c'est juste une complexité supplémentaire.

J'ai donc cessé d'utiliser Sequelize. De plus, j'ai renoncé à utiliser TOUTES les données extraites de la base de données dans les modèles. À mon avis, il est préférable d'abstraire complètement la récupération des données. Et les raisons sont les suivantes : imaginez que vous n'utilisez pas seulement MySQL (dans mon cas, j'utilise MySQL et MongoDB côte à côte), mais que vous pouvez obtenir vos données à partir de n'importe quel fournisseur de données et de n'importe quelle méthode de transport, par exemple SQL, no-SQL, système de fichiers, API externe, FTP, SSH, etc. Si vous essayez de faire tout cela dans les modèles, vous finirez par créer un code complexe et difficile à comprendre qui sera difficile à mettre à jour et à déboguer.

Maintenant, ce que vous voulez faire, c'est que les modèles obtiennent des données à partir d'une couche qui sait où et comment les obtenir, mais vos modèles n'utilisent que des méthodes API, par ex. fetch , save , delete etc. Et à l'intérieur de cette couche, vous avez des implémentations spécifiques pour des fournisseurs de données spécifiques. Par exemple, vous pouvez demander certaines données à partir d'un fichier PHP sur une machine locale, de l'API de Facebook, d'Amazon AWS ou d'un document HTML distant, etc.

PS certaines de ces idées ont été empruntées à Architecte par Cloud9 : http://events.yandex.ru/talks/300/

0 votes

Ce sont des points valables, mais je préfèrerais éviter de réimplémenter fetch , save , delete etc. en dehors de Sequelize étant donné que le cadre fournit déjà les moyens. Il est plus agréable, mais moins pratique, d'avoir une couche de récupération séparée. En même temps, vous pourriez probablement ajouter une couche d'abstraction de récupération autour de Sequelize, mais alors la solution est plus compliquée, pour un gain discutable.

0 votes

Ce tutoriel est très utile : exemple de séquençage+expression

0 votes

@mvbl-fst Vous venez de décrire une couche DAO. Disons que vous avez des utilisateurs dans une base de données SQL et différents utilisateurs sur le système de fichiers. Vous devriez avoir deux DAO qui abstraient la façon d'obtenir chacun d'eux, puis une couche métier qui concatène les utilisateurs ensemble (peut-être même adapter certaines propriétés) et les renvoie à votre route (la couche de présentation).

2voto

Ron Points 352

Je suis le guide officiel : http://sequelizejs.com/heroku qui possède un dossier de modèles, configure chaque module dans des fichiers séparés, et possède un fichier d'index pour les importer et définir la relation entre eux.

0 votes

Le lien n'est pas valide

1voto

natrixnatrix89 Points 16

Vous pouvez importer des modèles à partir d'autres fichiers avec sequelize.import http://sequelizejs.com/documentation#models-import

De cette façon, vous pouvez avoir un module singleton pour sequelize, qui charge ensuite tous les autres modèles.

En fait, cette réponse est assez similaire à celle de l'utilisateur 1778770.

1 votes

Cela fonctionne-t-il avec des dépendances circulaires ? Par exemple, si le modèle A a un FK vers le modèle B et que le modèle B a un FK vers le modèle A

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X