programing

속편화를 사용하는 노드 앱을 어떻게 구성합니까?

goodsources 2023. 8. 9. 20:43
반응형

속편화를 사용하는 노드 앱을 어떻게 구성합니까?

저는 속편 ORM을 사용하는 예제 nodejs 앱을 찾고 있습니다.

저의 주된 우려는 모델들이 서로 require() 의존성 루프 때문에 복잡한 관계를 맺고 있는 경우 별도의 js 파일에서 모델을 정의하는 것이 거의 불가능해 보인다는 것입니다.아마도 사람들은 매우 긴 한 파일에 모든 모델을 정의할 것입니다.

저는 주로 앱 전체에서 모델이 어떻게 정의되고 사용되는지에 관심이 있습니다.저는 제가 혼자서 하고 있는 것이 일을 하는 "좋은" 방법이라는 것을 증명하고 싶습니다.

단편소설

이 경우에는 파일에서 모델을 초기화하는 것이 아니라 초기화에 필요한 정보를 제공하고 중앙 집중식 모듈이 모델 설정 및 인스턴스화를 처리하도록 하는 것이 중요합니다.

단계는 다음과 같습니다.

  • 필드, 관계 및 옵션과 같은 모델에 대한 데이터가 포함된 모델 파일을 여러 개 보유합니다.
  • 모든 파일을 로드하고 모든 모델 클래스와 관계를 설정하는 싱글톤 모듈을 준비합니다.
  • app.js 파일에서 싱글톤 모듈을 설정합니다.
  • 사용하지 않는 싱글톤 모듈에서 모델 클래스 가져오기require모델 파일에서 대신 싱글톤에서 모델을 로드합니다.

더 긴 이야기

다음은 해당 소스 코드와 함께 이 솔루션에 대한 자세한 설명입니다.

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

편집: 이것은 매우 오래된 답변입니다! (자세한 내용은 아래를 읽어보십시오)

그것은 오래되고 많은 면에서 제한적입니다!

  • 첫째, @jingglethula가 코멘트에서 언급했듯이 (그리고 나도 그것을 경험했습니다) - 그러한 파일을 요구하는 데 문제가 있습니다.왜냐하면.require와 같은 방식으로 작동하지 않습니다.readdirSync!

  • 둘째, 관계가 매우 제한적입니다. 코드는 이러한 연결에 옵션을 제공하지 않으므로 생성할 수 없습니다.belongsToMany에 따라through양말을 .가장 기본적인 자산을 만들 수 있습니다.

  • 셋째 - 모델 관계에 매우 제한적입니다!코드를 자세히 읽어보면 관계가 배열이 아닌 개체라는 것을 알 수 있습니다. 따라서 동일한 유형의 연결을 둘 이상 만들려는 경우(예: 두 번)belongsTo) - 그럴 수 없습니다!

  • 번째 - 당신은 그런 싱글톤적인 것이 필요하지 않습니다.nodejs의 모든 모듈은 그 자체로 싱글톤이기 때문에 이 모든 것은 이유 없이 매우 복잡합니다.

팜의 답변을 봐야 합니다! (기사 링크가 끊겼지만 속편의 이 공식 샘플로 수정하겠습니다: https://github.com/sequelize/express-example/blob/master/models/index.js - 프로젝트 전체를 검색하여 무슨 일이 일어나고 있는지 알 수 있습니다.)

p.s. 사람들이 (저처럼) 새로운 답변을 보지 못할 정도로 지지를 받고 있기 때문에 이 게시물을 편집합니다.

편집: Github 페이지에서 동일한 게시물의 복사본으로 링크를 방금 변경했습니다.

속편화JS는 그들의 웹사이트에 이 문제를 해결하는 기사를 가지고 있습니다.

링크가 끊겼지만, 여기에서 작업 샘플 프로젝트를 찾아서 찾아볼 수 있습니다.이것이 더 나은 솔루션인 이유를 보려면 위의 편집된 답변을 참조하십시오.

기사에서 발췌:

  • models/index.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)
    

저는 사람들이 이 문제를 해결하는 것을 돕기 위해 속편 연결 패키지를 만들었습니다.이는 다음과 같은 Sequitize 제안 규칙을 따릅니다. http://sequelize.readthedocs.org/en/1.7.0/articles/express/

또한 인터페이스 측면에서도 Mongoose와 조금 더 유사한 기능을 합니다.모델이 위치한 위치 집합을 지정할 수 있으며 모델 파일과 일치하도록 사용자 지정 일치 함수를 정의할 수도 있습니다.

사용법은 기본적으로 다음과 같습니다.

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

그런 다음 모델에 액세스하여 다음과 같이 속편화할 수 있습니다.

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

이것이 누군가에게 도움이 되기를 바랍니다.

저는 Express.js app에서 Sufficialize를 사용하기 시작했습니다.곧 당신이 묘사하고 있는 본질적인 문제들에 부딪혔습니다.제가 Sufficientize를 잘 이해하지 못했을 수도 있지만, 한 테이블에서 선택하는 것 이상의 일을 하는 것은 제게 정말 편리하지 않았습니다.일반적으로 두 개 이상의 테이블 중에서 선택하거나 순수 SQL에서 통합을 사용하는 경우 별도의 쿼리를 실행해야 하며 노드의 비동기 특성으로 인해 복잡성이 가중될 뿐입니다.

그래서 저는 Sufficize를 사용하지 않게 되었습니다.또한 모델에서 DB에서 가져온 모든 데이터를 사용하지 않습니다.내 생각에는 데이터를 완전히 얻는 것을 추상화하는 것이 더 낫습니다.그 이유는 - MySQL(나의 경우 MySQL과 MongoDB를 나란히 사용)을 사용하는 것이 아니라 SQL, no-SQL, 파일 시스템, 외부 API, FTP, SSH 등의 모든 데이터 공급자와 전송 방법에서 데이터를 가져올 수 있다는 것입니다.모델에서 모든 작업을 수행하려고 하면 복잡하고 이해하기 어려운 코드가 생성되어 업그레이드 및 디버그가 어렵습니다.

이제 모델이 데이터를 가져오는 위치와 방법을 알고 있는 계층에서 데이터를 가져오지만 모델은 API 방법만 사용합니다.fetch,save,delete그리고 이 계층 안에는 특정 데이터 공급자를 위한 구체적인 구현이 있습니다.예를 들어 로컬 컴퓨터의 PHP 파일이나 Facebook API, Amazon AWS 또는 원격 HTML 문서 등에서 특정 데이터를 요청할 수 있습니다.

PS 이러한 아이디어 중 일부는 Architect 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, 을 따르고 있습니다. ▁which 은 모델 폴더가 있고, 각 모듈을 별도의 파일로 설정하고, 인덱스 파일을 가지고 있어 이들을 가져오고 그들 사이의 관계를 설정합니다.

샘플 모델 속편화

'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;
};


저에게 효과가 있었던 것은 다음과 같습니다.

  1. 다음과 같이 각 개별 모델에 대한 파일을 만듭니다.user.model.js폴더 안에models/user.model.js.
  2. 만들다index.jsmodels/index.js모든 모델을 가져옵니다.
  3. 연결 정의, 동기화 방법 실행index.js모든 모델을 내보냅니다.
  4. 작성database.jsSequalize(순차화) 및 Import(가져오기)에 대한 정보가 들어 있는 파일app.js

하나의 예models/user.model.js

import { DataTypes } from 'sequelize';
import { sequelize } from '../database.js';

export const User = sequelize.define("user",{
    uid:{
      type:DataTypes.STRING,
      allowNull:false,
      unique: true
    },
    email:{
      type:DataTypes.STRING,
      allowNull:true
    },
    firstName:{
      type:DataTypes.STRING,
      allowNull:true
    },
    lastName:{
      type:DataTypes.STRING,
      allowNull:true
    },
    companyWebsite:{
      type:DataTypes.STRING,
      allowNull:true
    },
    domain:{
      type:DataTypes.STRING,
      allowNull:true
    },
    hsPortalId:{
      type:DataTypes.INTEGER,
      allowNull:true
    },
    integrations:{
      type:DataTypes.STRING
    },
    brandedKeywords : {
      type:DataTypes.STRING
    },
    companyName: {
      type:DataTypes.STRING
    },
    companyStreet:{
      type:DataTypes.STRING
    },
    companyZip:{
      type:DataTypes.STRING
    },
    companyCountry:{
      type:DataTypes.STRING
    },
    vatId:{
      type:DataTypes.STRING
    },
    brand:{
      type:DataTypes.STRING
    },
    markets:{
      type:DataTypes.JSON
    },
    niche : {
      type:DataTypes.JSON
    }
  
  },{schema:"api"})

models/index.js

import { Billing } from './billing.model.js';
import { Competitor } from './competitors.model.js';
import { DemoAccount } from './demo.model.js';
import { Notification } from './notification.model.js';
import { Product } from './products.model.js';
import { Reseller } from './resellers.model.js';
import {Reseller_User} from './reseller_user.model.js'
import { Tag } from './tags.model.js';
import {User} from './user.model.js'

Reseller.belongsToMany(User, { through: Reseller_User });
User.belongsToMany(Reseller, { through: Reseller_User });

// this will create a UserId column on your Product table
// https://www.youtube.com/watch?v=HJGWu0cZUe8 40min
User.hasMany(Product,{onDelete: 'CASCADE',})
Product.belongsTo(User)

User.hasOne(DemoAccount,{onDelete: 'CASCADE',})
DemoAccount.belongsTo(User)

User.hasMany(Billing,{onDelete: 'CASCADE',})
Billing.belongsTo(User)

User.hasMany(Tag,{onDelete: 'CASCADE',})
Tag.belongsTo(User)

User.hasMany(Competitor,{onDelete: 'CASCADE'})
Competitor.belongsTo(User)

User.hasMany(Notification,{onDelete: 'CASCADE'})
Notification.belongsTo(User)


User.sync().then(
    () => console.log("Sync complete")
);

Reseller.sync().then(
() => console.log("Sync complete")
);

Reseller_User.sync().then(
() => console.log("Sync complete")
);

Product.sync().then(
() => console.log("Product Sync complete")
);

Competitor.sync().then(
() => console.log("Competitor Sync complete")
);

Notification.sync().then(
() => console.log("Competitor Sync complete")
);

Billing.sync().then(
() => console.log("Billing Sync complete")
);

Tag.sync().then(
() => console.log("Tag Sync complete")
);

DemoAccount.sync()

export { User, Reseller, Product, Competitor, Notification, DemoAccount, Billing, Tag };

// DemoAccount.sync({force:true}).then(
//   () => console.log("Sync complete")
// );

다을사용여다파모가있수져습다니델로 다른 에서 수 .sequelize.import http://sequelizejs.com/documentation#://sequelizejs.com/documentation#models-import

그런 식으로 속편화를 위해 싱글톤 모듈 하나를 사용할 수 있으며, 이 모듈은 다른 모든 모델을 로드합니다.

실제로 이 답변은 사용자 1778770의 답변과 상당히 유사합니다.

저는 속편 ORM을 사용하는 예제 nodejs 앱을 찾고 있습니다.

여러분은 PEAN을 보는 것에 관심이 있을 것입니다.JS 보일러 플레이트 용액.

PEAN.JS는 Postgre의 견고한 시작점을 제공하는 풀 스택 JavaScript 오픈 소스 솔루션입니다.SQL, Node.js, Express 및 AngularJS 기반 애플리케이션.

PEAN 프로젝트는 평균의 분기점입니다.JS 프로젝트(평균과 혼동해서는 안 됨).IO 또는 일반 평균 스택).

PEAN은 MongoDB와 Mongoose ORM을 Postgre로 대체합니다.SQL 및 후속 작업.평균의 주요 이점입니다.JS 프로젝트는 움직이는 조각이 많은 스택에 제공하는 조직입니다.

이에 대한 우아한 해결책을 제공하는 종속성 주입을 사용할 수도 있습니다.여기 하나 https://github.com/justmoon/reduct 이 있습니다.

언급URL : https://stackoverflow.com/questions/12487416/how-to-organize-a-node-app-that-uses-sequelize

반응형