Как организовать приложение узла, которое использует sequelize?



Я ищу пример nodejs приложение, которое использует sequelize ORM.



моя главная проблема заключается в том, что кажется почти невозможным определить ваши модели в отдельных JS-файлах, если эти модели имеют сложные отношения друг к другу из-за циклов зависимостей require (). Может быть, люди определяют все свои модели в одном файле, который очень длинный?



меня в основном интересует, как модели определяются и используются через приложение. Я хотел бы иметь некоторые проверки то, что я делаю сам по себе, - это "хороший" способ делать вещи.

851   10  

10 ответов:

рассказ

хитрость в данном случае заключается не в том, чтобы инициализировать модель на файл, но только для того, чтобы предоставить необходимую информацию для его инициализации и позволить централизованному модулю позаботиться о настройке и создании экземпляров моделей.

Итак, шаги:

  • есть несколько файлов модели с данными о модели, как поля, отношения и параметры.
  • есть одноэлементный модуль, который загружает все эти файлы и настроить все классы модели и отношения.
  • настройка ваш синглтон модуль в приложение.js файл.
  • получить классы моделей из модуля singleton не использовать require в файлах моделей вместо этого загрузите модели из синглтона.

более длинная история

вот более подробное описание данного решения с соответствующим источником код:

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

EDIT: это очень старый ответ! (Читать подробнее)

это старый и ограниченный во многих отношениях!

  • первый, как упоминалось в комментариях @jinglesthula (и я тоже это испытал) - есть проблемы с требованием этих файлов. Это потому что require не работает так же, как readdirSync!

  • второй - вы очень ограничено в отношениях-код не предоставляет опции к тем ассоциациям, так что вы можете создать belongsToMany как он должен through собственность. Вы можете сделать самый основной assocs.

  • третий - вы очень ограничены в модельных отношениях! Если вы внимательно прочтете код, вы увидите, что отношения-это объект вместо массив, так что если вы хотите сделать более одного ассоциации одного и того же типа (например, два раза belongsTo) - вы не можете!

  • четвертый - вы не нужны, что синглтон штуку. Каждый модуль в nodejs является синглтоном сам по себе, поэтому все это делает довольно сложным без причины.

вы должны увидеть ответ ферме! (Ссылка на статью сломана, но я исправлю это с помощью этого официального образца от sequelize: https://github.com/sequelize/express-example/blob/master/models/index.js - вы можете просмотреть весь проект, чтобы получить представление о том, что происходит).

p.s. Я редактирую этот пост, поскольку он настолько популярен, что люди даже не увидят новых ответов (как и я).

Edit: просто изменил ссылку на копию того же сообщения, но на странице Github

SequelizeJS имеет статью на их сайт, который решает эту проблему.

ссылка сломана, но вы можете найти рабочий образец проекта здесь и найдите его. См. отредактированный ответ выше, чтобы понять, почему это лучшее решение.

выдержка из статьи:

  • модели индекса/.js

    идея этого файла состоит в том, чтобы настроить соединение с базой данных и собрать всю модель определение. Как только все будет готово, мы вызовем метод, связанный с каждой из моделей. Этот метод можно использовать для связывания модели с другими.

          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)
    

Я создал пакет sequelize-connect, чтобы помочь людям справиться с этой проблемой. Это следует из предложенного здесь соглашения Sequelize:http://sequelize.readthedocs.org/en/1.7.0/articles/express/

кроме того, он также функционирует немного больше, как Мангуст с точки зрения его интерфейса. Он позволяет указать набор местоположений, в которых находятся ваши модели, а также позволяет определить пользовательскую функцию соответствия сопоставьте файлы модели.

использование в основном такой:

var orm = require('sequelize-connect');

orm.discover = ["/my/model/path/1", "/path/to/models/2"];      // 1 to n paths can be specified here
orm.connect(db, user, passwd, options);                        // initialize the sequelize connection and models

затем вы можете получить доступ к моделям и sequelize вот так:

var orm       = require('sequelize-connect');
var sequelize = orm.sequelize;
var Sequelize = orm.Sequelize;
var models    = orm.models;
var User      = models.User;

надеюсь, это поможет кому-то.

Я начал использовать Sequelize в Express.js app. Довольно скоро столкнулся с проблемами такого рода, которые вы описываете. Может быть, я не совсем понял Sequelize, но для меня делать что-то больше, чем просто выбирать из одной таблицы, было не очень удобно. И там, где обычно вы использовали бы select из двух или более таблиц или объединение в чистом SQL, вам пришлось бы запускать отдельные запросы, а с асинхронным характером узла это просто добавило сложности.

поэтому я отошел от использования Sequelize. Кроме того, я переключаюсь с использования любой выборки данных из БД в моделях. На мой взгляд, лучше абстрагироваться от получения данных полностью. И причины - представьте, что вы не просто используете MySQL (в моем случае я использую MySQL и MongoDB бок о бок), но вы можете получить свои данные от любого поставщика данных и любого транспортного метода, например SQL, no-SQL, файловой системы, внешнего API, FTP, SSH и т. д. Если вы попытаетесь сделать все это в моделях, вы в конечном итоге создадите сложный и трудный для понимания код, который было бы трудно обновить и отладить.

Теперь вы хотите, чтобы модели получали данные из слоя, который знает, где и как его получить, но ваши модели используют только методы API, например fetch,save,delete etc. И внутри этого уровня у вас есть конкретные реализации для конкретных поставщиков данных. Например, вы можете запросить определенные данные из файла PHP на локальном компьютере или из API Facebook, или из Amazon AWS, или из удаленного HTML-документа, так далее.

PS некоторые из этих идей были заимствованы из архитектор by Cloud9: http://events.yandex.ru/talks/300/

Я настроил его как ферму и описал в документации.

но у меня была дополнительная проблема, что в моих методах экземпляра и методах класса, которые я бы прикрепил к моделям в каждой функции, мне нужно было бы потребовать индексный файл, чтобы получить доступ к другим объектам базы данных.

решил, что делает их доступными для всех моделей.

var Config = require('../config/config');

 var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var _ = require('lodash');
var sequelize;
var db = {};

var dbName, dbUsername, dbPassword, dbPort, dbHost;
// set above vars

var sequelize = new Sequelize(dbName, dbUsername, dbPassword, {
dialect: 'postgres', protocol: 'postgres', port: dbPort, logging: false, host: dbHost,
  define: {
    classMethods: {
        db: function () {
                    return db;
        },
        Sequelize: function () {
                    return Sequelize;
        }

    }
  }
});


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 ('associate' in db[modelName]) {
      db[modelName].associate(db);
  }
});

module.exports = _.extend({
  sequelize: sequelize,
  Sequelize: Sequelize
}, db);

и в файле модели

var classMethods = {
  createFromParams: function (userParams) {
    var user = this.build(userParams);

    return this.db().PromoCode.find({where: {name: user.promoCode}}).then(function (code) {
        user.credits += code.credits;
                return user.save();
    });
  }

};

module.exports = function(sequelize, DataTypes) {
  return sequelize.define("User", {
  userId: DataTypes.STRING,
}, {  tableName: 'users',
    classMethods: classMethods
 });
};

Я сделал это только для методов класса, но вы могли также сделать то же самое, например, методы.

Я следую официальному руководству:http://sequelizejs.com/heroku, который имеет папку модели, настроить каждый модуль в отдельных файлах, и есть индексный файл для импорта их и установить отношения между ними.

вы можете импортировать модели из других файлов с sequelize.import http://sequelizejs.com/documentation#models-import

таким образом, вы можете иметь один одноэлементный модуль для sequelize, который затем загружает все другие модели.

на самом деле этот ответ очень похож на ответ пользователя 1778770.

Я ищу пример nodejs приложение, которое использует sequelize ORM.

вам может быть интересно посмотреть на PEAN.JS шаблонное решение.

PEAN.JS-это полнотекстовое решение JavaScript с открытым исходным кодом, которое обеспечивает прочную отправную точку для PostgreSQL, Node.приложения на основе js, Express и AngularJS.

в Проект PEAN-это вилка среднего.JS проект (не путать с MEAN.IO или generic средний стек).

PEAN заменяет MongoDB и Mongoose ORM на PostgreSQL и Sequelize. Основное преимущество среднего.Проект JS-это организация, которую он предоставляет стеку, который имеет много движущихся частей.

образец модели sequelize

'use strict';
const getRole   = require('../helpers/getRole')
const library   = require('../helpers/library')
const Op        = require('sequelize').Op

module.exports = (sequelize, DataTypes) => {
  var User = sequelize.define('User', {
    AdminId: DataTypes.INTEGER,
    name: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Name must be filled !!'
        },
      }
    },
    email: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Email must be filled !!'
        },
        isUnique: function(value, next) {
          User.findAll({
            where:{
              email: value,
              id: { [Op.ne]: this.id, }
            }
          })
          .then(function(user) {
            if (user.length == 0) {
              next()
            } else {
              next('Email already used !!')
            }
          })
          .catch(function(err) {
            next(err)
          })
        }
      }
    },
    password: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Password must be filled !!'
        },
        len: {
          args: [6, 255],
          msg: 'Password at least 6 characters !!'
        }
      }
    },
    role: {
      type: DataTypes.INTEGER,
      validate: {
        customValidation: function(value, next) {
          if (value == '') {
            next('Please choose a role !!')
          } else {
            next()
          }
        }
      }
    },
    gender: {
      type: DataTypes.INTEGER,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Gender must be filled !!'
        },
      }
    },
    handphone: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Mobile no. must be filled !!'
        },
      }
    },
    address: DataTypes.TEXT,
    photo: DataTypes.STRING,
    reset_token: DataTypes.STRING,
    reset_expired: DataTypes.DATE,
    status: DataTypes.INTEGER
  }, {
    hooks: {
      beforeCreate: (user, options) => {
        user.password = library.encrypt(user.password)
      },
      beforeUpdate: (user, options) => {
        user.password = library.encrypt(user.password)
      }
    }
  });

  User.prototype.check_password = function (userPassword, callback) {
    if (library.comparePassword(userPassword, this.password)) {
      callback(true)
    }else{
      callback(false)
    }
  }

  User.prototype.getRole = function() {
    return getRole(this.role)
  }

  User.associate = function(models) {
    User.hasMany(models.Request)
  }

  return User;
};

вы также можете использовать инъекцию зависимостей, которая обеспечивает элегантное решение для этого. Вот один https://github.com/justmoon/reduct

Comments

    Ничего не найдено.