bookshelf vs knex vs sequelize vs waterline
Node.js ORM Libraries
bookshelfknexsequelizewaterline类似的npm包:

Node.js ORM Libraries

Node.js ORM(对象关系映射)库提供了一种简化与数据库交互的方法,使开发者能够通过JavaScript对象而非SQL语句来操作数据库。这些库通常提供模型定义、数据验证、关系管理等功能,使得数据库操作更加直观和高效。选择合适的ORM库可以显著提高开发效率,减少错误,并增强代码的可维护性。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
bookshelf06,357-2386 年前MIT
knex020,267915 kB71124 天前MIT
sequelize030,3552.91 MB1,0242 个月前MIT
waterline05,3931.3 MB34-MIT

功能对比: bookshelf vs knex vs sequelize vs waterline

模型定义

  • bookshelf:

    Bookshelf允许开发者通过简单的JavaScript对象定义模型,并支持继承和扩展。它提供了丰富的API来定义模型的属性和关系,使得模型的创建和管理变得简单。

  • knex:

    Knex本身并不提供ORM功能,但它允许开发者通过查询构建器定义复杂的SQL查询。开发者可以使用Knex来创建和管理数据库表,但需要手动管理模型和关系。

  • sequelize:

    Sequelize提供了强大的模型定义功能,支持数据验证、钩子(hooks)和虚拟字段等特性。它允许开发者定义模型之间的关系,并提供了丰富的API来操作数据。

  • waterline:

    Waterline提供了一种统一的模型定义方式,支持多种数据存储。开发者可以通过简单的JSON格式定义模型,并使用Waterline的API进行数据操作。

关系管理

  • bookshelf:

    Bookshelf支持一对一、一对多和多对多关系的定义和管理。开发者可以轻松地在模型之间建立关系,并通过链式调用来查询相关数据。

  • knex:

    Knex不直接支持ORM关系管理,但开发者可以通过手动编写SQL查询来实现复杂的关系查询。它提供了灵活性,但需要更多的手动工作。

  • sequelize:

    Sequelize提供了强大的关系管理功能,支持多种关系类型,并允许开发者在模型之间定义关联。它自动处理关联查询,使得数据操作更加简便。

  • waterline:

    Waterline支持多种关系类型的定义,允许开发者在模型之间建立关联。它提供了简单的API来查询和操作相关数据。

查询构建

  • bookshelf:

    Bookshelf基于Knex构建,允许开发者使用Knex的查询构建器进行复杂查询。它结合了ORM的便利性和SQL的灵活性,使得查询构建变得高效。

  • knex:

    Knex是一个强大的SQL查询构建器,支持链式调用和多种数据库。它允许开发者以直观的方式构建复杂的SQL查询,适合需要精细控制的项目。

  • sequelize:

    Sequelize提供了丰富的查询API,允许开发者使用简单的JavaScript语法构建复杂的查询。它支持条件查询、分页和排序等功能,使得数据操作更加灵活。

  • waterline:

    Waterline提供了一种简单的查询API,允许开发者通过模型方法进行数据查询。虽然功能不如Knex强大,但对于常见的查询需求已足够使用。

事务支持

  • bookshelf:

    Bookshelf支持事务管理,允许开发者在多个数据库操作之间创建事务,以确保数据的一致性和完整性。

  • knex:

    Knex提供了强大的事务支持,允许开发者在多个查询之间创建事务,确保操作的原子性。它适合需要复杂数据库操作的场景。

  • sequelize:

    Sequelize内置了事务管理功能,允许开发者在模型操作之间创建事务,确保数据的一致性。它支持嵌套事务和并发控制。

  • waterline:

    Waterline对事务的支持有限,主要依赖于底层数据库的事务功能。对于简单的应用场景,通常足够使用,但在复杂场景下可能需要额外处理。

学习曲线

  • bookshelf:

    Bookshelf的学习曲线相对较平缓,特别是对于已经熟悉Knex的开发者。它的API设计简单易懂,适合中小型项目。

  • knex:

    Knex的学习曲线较低,特别是对于熟悉SQL的开发者。它的查询构建器直观易用,但对于不熟悉SQL的开发者可能需要一些时间适应。

  • sequelize:

    Sequelize的学习曲线相对较陡,尤其是对于初学者。它的功能丰富,但需要理解模型、关系和查询的复杂性。

  • waterline:

    Waterline的学习曲线较平缓,特别是对于Sails.js用户。它的API设计简单,适合快速开发和原型设计。

如何选择: bookshelf vs knex vs sequelize vs waterline

  • bookshelf:

    选择Bookshelf如果你需要一个简单易用的ORM,支持关系映射,并且希望与Knex.js紧密集成。Bookshelf适合中小型项目,提供了丰富的功能和灵活性。

  • knex:

    选择Knex如果你需要一个强大的SQL查询构建器,能够支持多种数据库,并且希望在SQL查询和ORM之间有更大的控制权。Knex适合需要复杂查询的项目。

  • sequelize:

    选择Sequelize如果你需要一个功能全面的ORM,支持多种数据库,并且希望使用丰富的模型定义和验证功能。Sequelize适合大型应用,提供了强大的事务管理和关系管理能力。

  • waterline:

    选择Waterline如果你需要一个适用于多种数据源的ORM,特别是在使用Sails.js框架时。Waterline支持多种数据库和数据存储,适合需要灵活数据模型的项目。

bookshelf的README

bookshelf.js

NPM Version Build Status Dependency Status devDependency Status

Bookshelf is a JavaScript ORM for Node.js, built on the Knex SQL query builder. It features both Promise-based and traditional callback interfaces, transaction support, eager/nested-eager relation loading, polymorphic associations, and support for one-to-one, one-to-many, and many-to-many relations.

It is designed to work with PostgreSQL, MySQL, and SQLite3.

Website and documentation. The project is hosted on GitHub, and has a comprehensive test suite.

Introduction

Bookshelf aims to provide a simple library for common tasks when querying databases in JavaScript, and forming relations between these objects, taking a lot of ideas from the Data Mapper Pattern.

With a concise, literate codebase, Bookshelf is simple to read, understand, and extend. It doesn't force you to use any specific validation scheme, and provides flexible, efficient relation/nested-relation loading and first-class transaction support.

It's a lean object-relational mapper, allowing you to drop down to the raw Knex interface whenever you need a custom query that doesn't quite fit with the stock conventions.

Installation

You'll need to install a copy of Knex, and either mysql, pg, or sqlite3 from npm.

$ npm install knex
$ npm install bookshelf

# Then add one of the following:
$ npm install pg
$ npm install mysql
$ npm install sqlite3

The Bookshelf library is initialized by passing an initialized Knex client instance. The Knex documentation provides a number of examples for different databases.

// Setting up the database connection
const knex = require('knex')({
  client: 'mysql',
  connection: {
    host     : '127.0.0.1',
    user     : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test',
    charset  : 'utf8'
  }
})
const bookshelf = require('bookshelf')(knex)

// Defining models
const User = bookshelf.model('User', {
  tableName: 'users'
})

This initialization should likely only ever happen once in your application. As it creates a connection pool for the current database, you should use the bookshelf instance returned throughout your library. You'll need to store this instance created by the initialize somewhere in the application so you can reference it. A common pattern to follow is to initialize the client in a module so you can easily reference it later:

// In a file named, e.g. bookshelf.js
const knex = require('knex')(dbConfig)
module.exports = require('bookshelf')(knex)

// elsewhere, to use the bookshelf client:
const bookshelf = require('./bookshelf')

const Post = bookshelf.model('Post', {
  // ...
})

Examples

Here is an example to get you started:

const knex = require('knex')({
  client: 'mysql',
  connection: process.env.MYSQL_DATABASE_CONNECTION
})
const bookshelf = require('bookshelf')(knex)

const User = bookshelf.model('User', {
  tableName: 'users',
  posts() {
    return this.hasMany(Posts)
  }
})

const Post = bookshelf.model('Post', {
  tableName: 'posts',
  tags() {
    return this.belongsToMany(Tag)
  }
})

const Tag = bookshelf.model('Tag', {
  tableName: 'tags'
})

new User({id: 1}).fetch({withRelated: ['posts.tags']}).then((user) => {
  console.log(user.related('posts').toJSON())
}).catch((error) => {
  console.error(error)
})

Official Plugins

  • Virtuals: Define virtual properties on your model to compute new values.
  • Case Converter: Handles the conversion between the database's snake_cased and a model's camelCased properties automatically.
  • Processor: Allows defining custom processor functions that handle transformation of values whenever they are .set() on a model.

Community plugins

  • bookshelf-cascade-delete - Cascade delete related models on destroy.
  • bookshelf-json-columns - Parse and stringify JSON columns on save and fetch instead of manually define hooks for each model (PostgreSQL and SQLite).
  • bookshelf-mask - Similar to the functionality of the {@link Model#visible} attribute but supporting multiple scopes, masking models and collections using the json-mask API.
  • bookshelf-schema - A plugin for handling fields, relations, scopes and more.
  • bookshelf-signals - A plugin that translates Bookshelf events to a central hub.
  • bookshelf-paranoia - Protect your database from data loss by soft deleting your rows.
  • bookshelf-uuid - Automatically generates UUIDs for your models.
  • bookshelf-modelbase - An alternative to extend Model, adding timestamps, attribute validation and some native CRUD methods.
  • bookshelf-advanced-serialization - A more powerful visibility plugin, supporting serializing models and collections according to access permissions, application context, and after ensuring relations have been loaded.
  • bookshelf-plugin-mode - Plugin inspired by the functionality of the {@link Model#visible} attribute, allowing to specify different modes with corresponding visible/hidden fields of model.
  • bookshelf-secure-password - A plugin for easily securing passwords using bcrypt.
  • bookshelf-default-select - Enables default column selection for models. Inspired by the functionality of the {@link Model#visible} attribute, but operates on the database level.
  • bookshelf-ez-fetch - Convenient fetching methods which allow for compact filtering, relation selection and error handling.
  • bookshelf-manager - Model & Collection manager to make it easy to create & save deep, nested JSON structures from API requests.

Support

Have questions about the library? Come join us in the #bookshelf freenode IRC channel for support on knex.js and bookshelf.js, or post an issue on Stack Overflow.

Contributing

If you want to contribute to Bookshelf you'll usually want to report an issue or submit a pull-request. For this purpose the online repository is available on GitHub.

For further help setting up your local development environment or learning how you can contribute to Bookshelf you should read the Contributing document available on GitHub.

F.A.Q.

Can I use standard node.js style callbacks?

Yes, you can call .asCallback(function(err, resp) { on any database operation method and use the standard (err, result) style callback interface if you prefer.

My relations don't seem to be loading, what's up?

Make sure to check that the type is correct for the initial parameters passed to the initial model being fetched. For example new Model({id: '1'}).load([relations...]) will not return the same as new Model({id: 1}).load([relations...]) - notice that the id is a string in one case and a number in the other. This can be a common mistake if retrieving the id from a url parameter.

This is only an issue if you're eager loading data with load without first fetching the original model. new Model({id: '1'}).fetch({withRelated: [relations...]}) should work just fine.

My process won't exit after my script is finished, why?

The issue here is that Knex, the database abstraction layer used by Bookshelf, uses connection pooling and thus keeps the database connection open. If you want your process to exit after your script has finished, you will have to call .destroy(cb) on the knex property of your Bookshelf instance or on the Knex instance passed during initialization. More information about connection pooling can be found over at the Knex docs.

How do I debug?

If you pass debug: true in the options object to your knex initialize call, you can see all of the query calls being made. You can also pass that same option to all methods that access the database, like model.fetch() or model.destroy(). Examples:

// Turning on debug mode for all queries
const knex = require('knex')({
  debug: true,
  client: 'mysql',
  connection: process.env.MYSQL_DATABASE_CONNECTION
})
const bookshelf = require('bookshelf')(knex)

// Debugging a single query
new User({id: 1}).fetch({debug: true, withRelated: ['posts.tags']}).then(user => {
  // ...
})

Sometimes you need to dive a bit further into the various calls and see what all is going on behind the scenes. You can use node-inspector, which allows you to debug code with debugger statements like you would in the browser.

Bookshelf uses its own copy of the bluebird Promise library. You can read up here for more on debugging Promises.

Adding the following block at the start of your application code will catch any errors not otherwise caught in the normal Promise chain handlers, which is very helpful in debugging:

process.stderr.on('data', (data) => {
  console.log(data)
})

How do I run the test suite?

See the CONTRIBUTING document on GitHub.

Can I use Bookshelf outside of Node.js?

While it primarily targets Node.js, all dependencies are browser compatible, and it could be adapted to work with other javascript environments supporting a sqlite3 database, by providing a custom Knex adapter. No such adapter exists though.

Which open-source projects are using Bookshelf?

We found the following projects using Bookshelf, but there can be more:

  • Ghost (A blogging platform) uses bookshelf. [Link]
  • Soapee (Soap Making Community and Resources) uses bookshelf. [Link]
  • NodeZA (Node.js social platform for developers in South Africa) uses bookshelf. [Link]
  • Sunday Cook (A social cooking event platform) uses bookshelf. [Link]
  • FlyptoX (Open-source Node.js cryptocurrency exchange) uses bookshelf. [Link]
  • And of course, everything on here use bookshelf too.