از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
Bookshelf.js: یک Node.js ORMON یکی از رایجترین منابعی که در زبانی مانند Node.js (عمدتاً یک زبان متمرکز بر وب) با آن تعامل خواهید داشت، پایگاههای داده هستند. و با توجه به اینکه SQL متداول ترین در بین انواع مختلف است، به یک کتابخانه خوب نیاز دارید تا به شما در تعامل با آن و ویژگی های متعدد آن کمک کند. Bookshelf.js…
سرفصلهای مطلب
یکی از رایج ترین منابعی که در زبانی مانند Node.js (عمدتاً یک زبان متمرکز بر وب) با آن تعامل خواهید داشت، پایگاه داده ها هستند. و با توجه به اینکه SQL متداول ترین در بین انواع مختلف است، به یک کتابخانه خوب نیاز دارید تا به شما در تعامل با آن و ویژگی های متعدد آن کمک کند.
Bookshelf.js یکی از محبوبترین بستههای ORM Node.js است. از Knex.js، که یک سازنده پرس و جو انعطاف پذیر است که با PostgreSQL، MySQL و SQLite3 کار می کند. Bookshelf.js می سازد روی بالاتر از این، با ارائه عملکرد برای ایجاد مدل های داده، ایجاد روابط بین این مدل ها، و سایر وظایف رایج مورد نیاز هنگام پرس و جو از پایگاه داده.
قفسه کتاب همچنین از چندین پشتیبان پایگاه داده پشتیبانی می کند، مانند MySQL، PostgreSQL، و SQLite. به این ترتیب می توانید به راحتی پایگاه داده ها را در صورت نیاز تغییر دهید یا از یک DB کوچکتر مانند SQLite در طول توسعه و Postgre در تولید استفاده کنید.
در طول این مقاله به شما نشان خواهم داد که چگونه می توانید از این Node ORM بیشترین بهره را ببرید، از جمله اتصال به پایگاه داده، ایجاد مدل ها و ذخیره/بارگیری اشیا.
قفسه کتاب را نصب کنید
Bookshelf با اکثر بستههای Node کمی متفاوت است، زیرا تمام وابستگیهای خود را به طور خودکار برای شما نصب نمیکند. در این صورت، باید Knex را به همراه Bookshelf به صورت دستی نصب کنید:
$ npm install knex --save
$ npm install bookshelf --save
علاوه بر آن، باید انتخاب کنید که با کدام پایگاه داده میخواهید از Bookshelf استفاده کنید. انتخاب های شما عبارتند از:
اینها را می توان با:
$ npm install pg --save
$ npm install mysql --save
$ npm install mariasql --save
$ npm install sqlite3 --save
یکی از کارهایی که من تمایل دارم با پروژه های خود انجام دهم، نصب یک DB درجه تولید (مانند Postgre) با استفاده از آن است --save
، در حین استفاده --save-dev
برای یک DB کوچکتر مانند SQLite برای استفاده در طول توسعه.
$ npm install pg --save
$ npm install sqlite3 --save-dev
به این ترتیب میتوانیم به راحتی بین پایگاههای داده در تولید و توسعه جابهجا شویم، بدون اینکه نگران سیل شدن محیط تولید من با وابستگیهای غیر ضروری باشیم.
اتصال به پایگاه داده
تمام توابع سطح پایین، مانند اتصال به پایگاه داده، توسط کتابخانه Knex زیرین اداره می شود. بنابراین، به طور طبیعی، به منظور مقداردهی اولیه شما bookshelf
به عنوان مثال شما نیاز به ایجاد یک knex
برای مثال اول، مانند این:
var knex = require('knex')({
client: 'sqlite3',
connection: {
filename: './db.sqlite'
}
});
var bookshelf = require('bookshelf')(knex);
و اکنون می توانید از آن استفاده کنید bookshelf
نمونه ای برای ایجاد مدل های خود
تنظیم جداول
Knex، همانطور که وب سایت خود بیان می کند، یک سازنده پرس و جوی SQL “با باتری ها است” است، بنابراین می توانید تقریباً هر کاری را که می خواهید با دستورات SQL خام انجام دهید از طریق Knex انجام دهید. یکی از این ویژگی های مهم جدول سازی و دستکاری است. Knex می تواند مستقیماً برای راه اندازی طرحواره خود در پایگاه داده استفاده شود (به مقداردهی اولیه پایگاه داده، مهاجرت طرح و غیره فکر کنید).
بنابراین اول از همه، شما می خواهید جدول خود را با استفاده از آن ایجاد کنید knex.schema.createTable()
، که یک شی جدول را ایجاد می کند و برمی گرداند که شامل یک دسته از طرحواره سازی توابع، مانند table.increments()
، table.string()
، و table.date()
. برای هر مدلی که ایجاد میکنید، باید برای هر کدام یک کاری شبیه به این انجام دهید:
knex.schema.createTable('users', function(table) {
table.increments();
table.string('name');
table.string('email', 128);
table.string('role').defaultTo('admin');
table.string('password');
table.timestamps();
});
در اینجا می بینید که ما جدولی به نام «کاربران» ایجاد می کنیم که سپس با ستون های «نام»، «ایمیل»، «نقش» و «رمز عبور» مقداردهی اولیه می کنیم. حتی میتوانیم یک قدم جلوتر برویم و حداکثر طول یک ستون رشته (128 برای ستون ‘ایمیل’) یا یک مقدار پیشفرض (‘admin’ برای ستون ‘نقش’) را مشخص کنیم.
برخی از توابع راحتی نیز ارائه شده است، مانند timestamps()
. این تابع دو ستون مهر زمان را به جدول اضافه می کند. created_at
و updated_at
. اگر از این استفاده می کنید، تنظیم را نیز در نظر بگیرید hasTimestamps
دارایی به true
در مدل خود (به «ایجاد یک مدل» در زیر مراجعه کنید).
چندین گزینه دیگر وجود دارد که میتوانید برای هر جدول/ستون مشخص کنید، بنابراین من قطعاً توصیه میکنم تمام آن را بررسی کنید. مستندات Knex برای جزئیات بیشتر
ایجاد یک مدل
یکی از اشکالات من در مورد Bookshelf این است که شما همیشه به یک مقدار اولیه نیاز دارید bookshelf
به عنوان مثال برای ایجاد یک مدل، بنابراین اگر همه مدلهای خود را در فایلهای مختلف نگه دارید، ساختار برخی از برنامهها میتواند کمی آشفته باشد. من شخصا ترجیح می دهم فقط بسازم bookshelf
استفاده جهانی global.bookshelf = bookshelf
، اما این لزوما بهترین راه برای انجام آن نیست.
به هر حال، بیایید ببینیم برای ایجاد یک مدل ساده چه چیزی لازم است:
var User = bookshelf.Model.extend({
tableName: 'users',
hasTimestamps: true,
verifyPassword: function(password) {
return this.get('password') === password;
}
}, {
byEmail: function(email) {
return this.forge().query({where:{ email: email }}).fetch();
}
});
در اینجا ما یک مدل بسیار ساده برای نشان دادن برخی از ویژگی های موجود داریم. اول از همه، فقط اموال مورد نیاز است tableName
، که به مدل می گوید داده ها را از کجا در DB ذخیره و بارگذاری کند. بدیهی است که راه اندازی یک مدل بسیار کم است زیرا همه اعلان طرح در جاهای دیگر انجام شده است.
در مورد بقیه ویژگی ها/توابع، در اینجا خلاصه ای سریع از چه چیزی است User
شامل می شود:
tableName
: رشته ای که به مدل می گوید داده ها را از کجا در DB ذخیره و بارگذاری کند (الزامی)hasTimestamps
: یک مقدار بولی که به مدل می گوید که آیا ما نیاز داریم یا خیرcreated_at
وupdated_at
مهرهای زمانیverifyPassword
: یک تابع نمونهbyEmail
: یک تابع کلاس (استاتیک).
بنابراین، برای مثال، ما استفاده خواهیم کرد byEmail
به عنوان یک راه کوتاه تر برای پرس و جو از کاربر با آدرس ایمیل او:
User.byEmail('(email protected)').then(function(u) {
console.log('Got user:', u.get('name'));
});
به روش دسترسی به داده های مدل در Bookshelf توجه کنید. به جای استفاده از یک ویژگی مستقیم (مانند u.name
، باید از آن استفاده کنیم .get()
روش.
پشتیبانی ES6
در زمان نگارش این مقاله، به نظر نمیرسد که Bookshelf از ES6 پشتیبانی کامل داشته باشد (نگاه کنید به این مساله). با این حال، هنوز هم می توانید بسیاری از کدهای مدل خود را با استفاده از کلاس های جدید ES6 بنویسید. با استفاده از مدل از بالا، میتوانیم آن را با استفاده از new دوباره ایجاد کنیم class
نحوی مانند این:
class User extends bookshelf.Model {
get tableName() {
return 'users';
}
get hasTimestamps() {
return true;
}
verifyPassword(password) {
return this.get('password') === password;
}
static byEmail(email) {
return this.forge().query({where:{ email: email }}).fetch();
}
}
و اکنون می توان از این مدل دقیقاً مانند مدل قبلی استفاده کرد. این روش هیچ مزیت عملکردی به شما نمی دهد، اما برای برخی افراد آشناتر است، بنابراین اگر می خواهید از آن بهره ببرید.
مجموعه ها
در Bookshelf همچنین باید یک شی جداگانه برای مجموعه های یک مدل مشخص ایجاد کنید. بنابراین اگر می خواهید عملیاتی را انجام دهید روی چندگانه User
s در همان زمان، به عنوان مثال، شما نیاز به ایجاد یک Collection
.
در ادامه مثال ما از بالا، در اینجا روش ایجاد آن است Users
Collection
هدف – شی:
var Users = bookshelf.Collection.extend({
model: User
});
خیلی ساده، درست است؟ اکنون میتوانیم به راحتی برای همه کاربران با استفاده از آن پرس و جو کنیم (اگرچه این قبلاً با استفاده از یک مدل ممکن بود .fetchAll()
):
Users.forge().fetch().then(function(users) {
console.log('Got a bunch of users!');
});
حتی بهتر از آن، اکنون می توانیم از چند روش مدل خوب استفاده کنیم روی مجموعه به عنوان یک کل، به جای اینکه مجبور باشید روی هر مدل به طور جداگانه تکرار کنید. یکی از این روش ها که به نظر می رسد در وب اپلیکیشن ها بسیار مورد استفاده قرار می گیرد، این است .toJSON()
:
exports.get = function(req, res) {
Users.forge().fetch().then(function(users) {
res.json(users.toJSON());
});
};
این یک شی جاوا اسکریپت ساده از کل مجموعه را برمی گرداند.
مدل های خود را گسترش دهید
به عنوان یک توسعه دهنده، یکی از مهم ترین اصولی که من رعایت کرده ام این است خشک اصل (تکرار نکن) این تنها یکی از دلایلی است که چرا پسوند مدل/شما برای طراحی نرم افزار شما بسیار مهم است.
با استفاده از قفسه کتاب .extend()
متد، شما می توانید تمام ویژگی ها، متدهای نمونه و متدهای کلاس یک مدل پایه را به ارث ببرید. به این ترتیب میتوانید روشهای پایهای را که قبلاً ارائه نشدهاند، ایجاد کنید و از آنها استفاده کنید .find()
، .findOne()
، و غیره.
یک مثال عالی از پسوند مدل در قفسه کتاب-مدل پایه پروژه، که بسیاری از روشهای گمشده را ارائه میکند که انتظار دارید در اکثر ORMها استاندارد باشند.
اگر بخواهید مدل پایه ساده خود را بسازید، ممکن است به شکل زیر باشد:
var model = bookshelf.Model.extend({
hasTimestamps: ('created_at', 'updated_at'),
}, {
findAll: function(filter, options) {
return this.forge().where(filter).fetchAll(options);
},
findOne: function(query, options) {
return this.forge(query).fetch(options);
},
create: function(data, options) {
return this.forge(data).save(null, options);
},
});
اکنون همه مدل های شما می توانند از این روش های مفید استفاده کنند.
ذخیره و به روز رسانی مدل ها
بسته به این، چند روش مختلف برای ذخیره مدل ها در Bookshelf وجود دارد روی تنظیمات و قالب داده های شما
اولین و واضح ترین راه این است که فقط تماس بگیرید .save()
روی یک نمونه مدل
var user = new User();
user.set('name', 'Joe');
user.set('email', '(email protected)');
user.set('age', 28);
user.save().then(function(u) {
console.log('User saved:', u.get('name'));
});
این برای مدلی که خودتان ایجاد میکنید (مانند مدل بالا)، یا با نمونههای مدلی که از یک تماس درخواستی به شما بازگردانده میشوند، کار میکند.
گزینه دیگر استفاده از .forge()
روش و آن را با داده ها مقداردهی اولیه کنید. “Forge” در واقع فقط یک راه کوتاه برای ایجاد یک مدل جدید است (مانند new User()
). اما به این ترتیب برای ایجاد مدل قبل از شروع رشته query/save نیازی به خط اضافی ندارید.
استفاده کردن .forge()
، کد بالا به شکل زیر خواهد بود:
var data = {
name: 'Joe',
email: '(email protected)',
age: 28
}
User.forge(data).save().then(function(u) {
console.log('User saved:', u.get('name'));
});
این واقعاً هیچ خط کدی را برای شما ذخیره نمی کند، اما اگر می تواند راحت باشد data
در واقع JSON ورودی یا چیزی شبیه به آن است.
در حال بارگذاری مدل ها
در اینجا من در مورد روش بارگیری مدل ها از پایگاه داده با Bookshelf صحبت خواهم کرد.
در حالی که .forge()
واقعاً در ذخیره اسناد به ما کمک چندانی نکرد، مطمئناً در بارگیری آنها کمک می کند. ایجاد یک نمونه مدل خالی فقط برای بارگیری داده ها از پایگاه داده کمی ناخوشایند است، بنابراین از .forge()
بجای.
ساده ترین مثال برای بارگذاری این است که فقط یک مدل را با استفاده از آن واکشی کنید .fetch()
:
User.forge({email: '(email protected)'}).fetch().then(function(user) {
console.log('Got user:', user.get('name'));
});
تنها کاری که ما در اینجا انجام می دهیم این است که یک مدل واحد را که با پرس و جوی داده شده مطابقت دارد، بگیریم. همانطور که می توانید تصور کنید، پرس و جو می تواند به همان اندازه که شما می خواهید پیچیده باشد (مانند محدودیت روی name
و age
ستون ها نیز).
درست مانند SQL ساده قدیمی، میتوانید پرس و جو و دادههای بازگردانده شده را تا حد زیادی سفارشی کنید. به عنوان مثال، این پرس و جو فقط داده هایی را که برای احراز هویت یک کاربر نیاز داریم به ما می دهد:
var email = '...';
var plainTextPassword = '...';
User.forge({email: email}).fetch({columns: ('email', 'password_hash', 'salt')})
.then(function(user) {
if (user.verifyPassword(plainTextPassword)) {
console.log('User logged in!');
} else {
console.log('Authentication failed...');
}
});
با در نظر گرفتن این حتی بیشتر، می توانیم از آن استفاده کنیم withRelations
گزینه ای برای بارگذاری خودکار مدل های مرتبط که در بخش بعدی خواهیم دید.
روابط مدل
در بسیاری از برنامهها، مدلهای شما نیاز به ارجاع به مدلهای دیگر دارند که در SQL با استفاده از کلیدهای خارجی به دست میآید. یک نسخه ساده از این در Bookshelf از طریق روابط پشتیبانی می شود.
در مدل خود، میتوانید به Bookshelf بگویید که مدلهای دیگر دقیقاً چگونه با یکدیگر مرتبط هستند. این امر با استفاده از belongsTo()
، hasMany()
، و hasOne()
(در میان دیگران) روش ها.
بنابراین فرض کنید شما دو مدل دارید، User و Address. کاربر می تواند چندین آدرس (یکی برای حمل و نقل، یکی برای صورتحساب و غیره) داشته باشد، اما یک آدرس می تواند تنها به یک کاربر تعلق داشته باشد. با توجه به این، ممکن است مدل های خود را به این صورت تنظیم کنیم:
var User = bookshelf.Model.extend({
tableName: 'users',
addresses: function() {
return this.hasMany('Address', 'user_id');
},
});
var Address = bookshelf.Model.extend({
tableName: 'addresses',
user: function() {
return this.belongsTo('User', 'user_id');
},
});
توجه داشته باشید که من از افزونه رجیستری در اینجا، که به من امکان می دهد با یک رشته به مدل Address مراجعه کنم.
این hasMany()
و belongsTo()
Method به Bookshelf می گوید که چگونه هر مدل با یکدیگر مرتبط است. کاربر آدرسهای زیادی دارد، در حالی که آدرس متعلق به یک کاربر است. آرگومان دوم نام ستون است که مکان کلید مدل را نشان می دهد. در این مورد، هر دو مدل ها به user_id
ستون در جدول آدرس
حال میتوانیم با استفاده از این از این رابطه استفاده کنیم withRelated
گزینه روی .fetch()
مواد و روش ها. بنابراین اگر من می خواستم یک کاربر را بارگذاری کنم و همه آدرس های آنها را با یک تماس می توانم انجام دهم:
User.forge({email: '(email protected)'}).fetch({withRelated: ('addresses')})
.then(function(user) {
console.log('Got user:', user.get('name'));
console.log('Got addresses:', user.related('addresses'));
});
اگر بخواهیم مدل User را واکشی کنیم بدون را withRelated
سپس گزینه user.related('addresses')
فقط یک شی مجموعه خالی را برمی گرداند.
مطمئن شوید که از این روش های ارتباطی استفاده کنید، استفاده از آنها بسیار ساده تر از ایجاد SQL JOIN های خودتان است 🙂
خوب
قفسه کتاب یکی از آن کتابخانه هایی است که به نظر می رسد سعی می کند بیش از حد پف نکند و فقط به ویژگی های اصلی پایبند باشد. این عالی است زیرا ویژگی های آن هستند خیلی خوب کار می کنند
Bookshelf همچنین دارای یک API زیبا و قدرتمند است که به شما امکان می دهد به راحتی برنامه خود را بسازید روی بالای آن بنابراین مجبور نیستید با روشهای سطح بالایی که فرضیات ضعیفی ایجاد میکنند دست و پنجه نرم کنید روی چگونه از آنها استفاده می شود
بد
اگرچه من فکر میکنم خوب است که Bookshelf/Knex برخی از عملکردهای سطح پایینتر را در اختیار شما قرار میدهد، هنوز هم فکر میکنم جایی برای بهبود وجود دارد. به عنوان مثال، تمام تنظیمات جدول/شما به شما واگذار شده است، و راه آسانی برای تعیین طرح شما (مانند یک شیء JS ساده) در مدل وجود ندارد. تنظیم جدول/طرحواره باید در فراخوانی های API مشخص شود، که خواندن و اشکال زدایی آن چندان آسان نیست.
یکی دیگر از مشکلات من این است که چگونه آنها بسیاری از روش های کمکی را که باید با مدل پایه استاندارد باشد، کنار گذاشتند .create()
، .findOne()
، .upsert()
و اعتبار سنجی داده ها دقیقاً به همین دلیل است که به آن اشاره کردم bookshelf-modelbase
پروژه را زودتر انجام دهید زیرا بسیاری از این شکاف ها را پر می کند.
نتیجه
به طور کلی، من کاملاً طرفدار استفاده از Bookshelf/Knex برای کارهای SQL شدهام، اگرچه فکر میکنم برخی از مشکلاتی که به آن اشاره کردم ممکن است برای بسیاری از توسعهدهندگانی باشد که به استفاده از ORMهایی که تقریباً همه چیز را انجام میدهند، غیرفعال باشد. آنها را خارج از جعبه از سوی دیگر، برای توسعه دهندگان دیگری که دوست دارند کنترل زیادی داشته باشند، این کتابخانه عالی برای استفاده است.
در حالی که سعی کردم در این مقاله تا حد امکان از API اصلی را پوشش دهم، هنوز چند ویژگی وجود دارد که نتوانستم آنها را لمس کنم. روی، پس حتما بررسی کنید مستندات پروژه برای اطلاعات بیشتر.
آیا از Bookshelf.js یا Knex.js استفاده کرده اید؟ شما چی فکر میکنید؟ در نظرات به ما اطلاع دهید!
(برچسبها برای ترجمه)# جاوا اسکریپت
منتشر شده در 1403-01-29 00:11:04