sequelize ORMを使用するnodejsアプリの例を探しています。
require()依存ループのためにモデルが互いに複雑な関係を持っている場合、モデルを別々のjsファイルで定義することはほとんど不可能に思われるのが私の主な懸念です。多分人々はすべてのモデルを非常に長い1つのファイルで定義しますか?
私は主に、モデルがどのように定義され、アプリ全体で使用されるかに興味があります。私が自分でやっていることは、物事を行うための「良い」方法であることを検証したいのですが。
sequelize ORMを使用するnodejsアプリの例を探しています。
require()依存ループのためにモデルが互いに複雑な関係を持っている場合、モデルを別々のjsファイルで定義することはほとんど不可能に思われるのが私の主な懸念です。多分人々はすべてのモデルを非常に長い1つのファイルで定義しますか?
私は主に、モデルがどのように定義され、アプリ全体で使用されるかに興味があります。私が自分でやっていることは、物事を行うための「良い」方法であることを検証したいのですが。
回答:
この場合のトリックは、モデルを初期化することはないでファイルが、ちょうどその初期化のためのnecesary情報を提供し、モデルのセットアップおよびインスタンス化の集中管理モジュールの世話をしてみましょう。
したがって、手順は次のとおりです。
require
代わりにシングルトンからモデルをロードします。このソリューションの詳細な説明と、対応するソースコードを次に示します。
http://jeydotc.github.io/blog/2012/10/30/EXPRESS-WITH-SEQUELIZE.html
それは古く、多くの点で制限されています!
最初に、@ jinglesthulaがコメントで述べたように(そして私も経験しました)、これらのファイルの要求に問題があります。とrequire
同じように動作しないためreaddirSync
です!
第二に -あなたがしている非常に関係が制限-コードが用意されていませんオプションあなたがいるので、これらの団体へのUNABLE作成するbelongsToMany
ことが必要とthrough
財産を。最も基本的な関連を作成できます。
第三に、あなたはモデルの関係が非常に限られています!コードをよく読むと、RelationsがArrayではなくObjectであることがわかります。したがって、同じタイプの関連付けを2つ以上作成したい場合(2回持つ場合など)はできません。belongsTo
第四 -あなたはそのシングルトンの物事を必要としません。nodejs内のすべてのモジュールはそれ自体がシングルトンであるため、これによりすべてが複雑になり、理由はまったくありません。
ファームの答えが表示されます。(記事へのリンクは壊れていますが、sequelizeの次の公式サンプルで修正します:https : //github.com/sequelize/express-example/blob/master/models/index.js-閲覧できます何が起こっているのかを知るためのプロジェクト全体)。
ps私はこの投稿を編集しているので、あまりにも賛成されているので、(私が行ったように)新しい回答は表示されません。
編集:リンクを同じ投稿のコピーに変更しましたが、Githubページにあります
require
node内のすべてのdモジュールは、コードが1回実行されてからキャッシュされるため、ある意味でシングルトンであり、次回それらを必要とするときに、キャッシュされたオブジェクト参照を取得するという印象を受けました。これは全体像ではありませんか?
SequelizeJSのウェブサイトに、この問題を解決する記事があります。
リンクは壊れていますが、ここで動作するサンプルプロジェクトを見つけて参照できます。これがより良いソリューションである理由を確認するには、上記の編集された回答を参照してください。
記事からの抜粋:
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)
sequelize
モデルファイルの変数にアクセスできるため、を使用して他のモデルにアクセスできますsequelize.models.modelName
。
この問題への対処を支援するために、sequelize-connectパッケージを作成しました。それはここSequelize提案規則に従います。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アプリでSequelizeを使い始めました。すぐに、あなたが説明している自然の問題に遭遇しました。たぶん私はSequelizeを完全に理解していなかったかもしれませんが、1つのテーブルから選択すること以上のことをすることは私にとって本当に便利ではありませんでした。通常、2つ以上のテーブルからの選択、またはピュアSQLのユニオンを使用する場合、個別のクエリを実行する必要があり、ノードの非同期の性質により、複雑さが増します。
そのため、Sequelizeの使用をやめました。さらに、モデルでDBからフェッチするすべてのデータの使用から切り替えています。私の意見では、取得するデータを完全に抽象化する方が良いです。そして理由は-MySQLを使用するだけではない(私の場合、MySQLとMongoDBを並べて使用する)と想像してください。ただし、SQL、no-SQLなどの任意のデータプロバイダーとトランスポートメソッドからデータを取得できます。ファイルシステム、外部API、FTP、SSHなど。すべてをモデルで実行しようとすると、最終的には複雑で理解しにくいコードが作成され、アップグレードやデバッグが難しくなります。
ここで、モデルがデータを取得する場所と方法を知っているレイヤーからデータを取得するようにしますが、モデルfetch
はsave
、delete
などのAPIメソッドのみを使用します。このレイヤー内には、特定のデータプロバイダーの特定の実装があります。たとえば、ローカルマシンのPHPファイル、Facebook API、Amazon AWS、リモートHTMLドキュメントなどから特定のデータをリクエストできます。
PSこれらのアイデアのいくつかは、Cloud9によってArchitectから借用されました:http : //events.yandex.ru/talks/300/
fetch
、save
、delete
などの外部のSequelize
フレームワークはすでにの手段を提供することを与えられました。別のフェッチングレイヤーを使用する方が便利ですが、あまり便利ではありません。同時に、おそらくSequelizeの周囲にフェッチする抽象化レイヤーを追加することもできますが、その場合、解決策はより複雑になり、議論の余地があるでしょう。
私はそれをファームとしてセットアップし、ドキュメントで説明しています。
しかし、各関数のモデルにアタッチするインスタンスメソッドとクラスメソッドで、他のデータベースオブジェクトを保持するためにインデックスファイルが必要になるという追加の問題がありました。
すべてのモデルがアクセスできるようにすることで解決しました。
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には、modelsフォルダーがあり、各モジュールを個別のファイルに設定し、それらをインポートしてそれらの間の関係を設定するためのインデックスファイルがあります。
サンプルモデルの続編
'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;
};
http://sequelizejs.com/documentation#models-importを使用して、他のファイルからモデルをインポートできますsequelize.import
そうすることで、sequelizeのシングルトンモジュールを1つ持つことができ、それが他のすべてのモデルをロードします。
実際、この回答はuser1778770の回答と非常によく似ています。
sequelize ORMを使用するnodejsアプリの例を探しています。
PEAN.JSのボイラープレートソリューションをご覧ください。
PEAN.JSは、フルスタックのJavaScriptオープンソースソリューションであり、PostgreSQL、Node.js、Express、およびAngularJSベースのアプリケーションの確実な出発点を提供します。
PEANプロジェクトはMEAN.JSプロジェクトのフォークです(MEAN.IOまたは汎用 MEANスタックと混同しないでください)。
PEANは、MongoDBとMongoose ORMをPostgreSQLとSequelizeに置き換えます。MEAN.JSプロジェクトの主な利点は、多くの動く部分があるスタックに提供する組織です。
これに対するエレガントなソリューションを提供する依存関係注入を使用することもできます。これがhttps://github.com/justmoon/reductです