Skip to content

Navigation Menu

Sign in
Sign up
This repository was archived by the owner on Nov 10, 2023. It is now read-only.

Repository files navigation

Requelize

Installation

yarn add requelize joi

joi is a peer dependency to create schemas

Configuration

const requelize = require('requelize')({ host: 'localhost', db: 'myApp' })

Options are passed to rethinkdbdash options

Debugging

requelize uses debug to debug your apps. You can use the DEBUG environment variable as follows:

DEBUG=requelize:* yarn start

Model definition

const joi = require('joi')
const User = requelize.model('User', {
 email: joi.string()
 firstname: joi.string(),
 lastname: joi.string()
})
User.index('email')

You might also pass a third argument to requelize.model that looks like this: { primaryKey: string } Primary keys allowed are: guid and integers

Querying

requelize.sync()
 .then(() => User.getAll('john.doe@example.com', { index: 'email' }))
 .then((users) => {
 console.log(users)
 })

First you need to sync database with requelize.sync. To query documents, you can use any rql commands. User is a sugar syntax for r.db('...').table('User').

Create / Update / Delete

You can instanciate models to create documents

const user = new User({
 email: 'john.doe@example.com',
 firstname: 'John',
 lastname: 'Doe'
})
user
 .save()
 .then(() => console.log(user.id))

You can update users with subsequent save calls

user.email = 'john@doe.com'
user.save()

You can delete documents with the delete model method.

user
 .delete()
 .then(() => assert.equal(null, user.id))

Relationships

hasOne

User.hasOne('Role', 'role', 'User_id')

Arguments are:

  1. Relation Model name (the first argument of requelize.model)
  2. The virutal field on the instance (so that you have user.role.id)
  3. The foreign key to use. requelize defaults to SelfModel_id

hasMany

User.hasMany('Post', 'posts', 'User_id')

Arguments are:

  1. Relation Model name (the first argument of requelize.model)
  2. The virutal field on the instance (so that you have user.posts[0].id)
  3. The foreign key to use. requelize defaults to SelfModel_id

The foreign key have to be equal to the local key used on belongsTo method

belongsTo

Role.belongsTo('User', 'user', 'User_id')
Post.belongsTo('User', 'user', 'User_id')

Arguments are:

  1. Relation Model name (the first argument of requelize.model)
  2. The virutal field on the instance (so that you have role.user.id or post.user.id)
  3. The local key to use (usually: model_id or modelId or Model_id). requelize defaults to Model_id

belongsToMany

User.belongsToMany('Right', 'rights')
Right.belongsToMany('User', 'users')

Arguments are:

  1. Relation Model name (the first argument of requelize.model)
  2. The virutal field on the instance (so that you have right.users[0].id or user.rights[0].id)
  3. An optional join table name. Default is ModelA_ModelB with ModelA and ModelB being sorted

embed and saveAll

To query an instance with its relationships, you can use embed:

User
 .get('someId')
 .embed({
 role: true,
 rights: true,
 group: {
 admin: true
 }
 })
 .then((user) => {
 console.log(user.role.id)
 assert.equal(true, user.role instanceof Role)
 })

You may have nested relations with sub object (as in group: { admin: true })

To save an instance with its relationships, you can use saveAll:

user.role = roleA
user.rights = [ rightA, rightB ]
user.saveAll({
 role: true,
 rights: true
})

You can also save an array of ids with hasMany or belongsToMany:

user.role = roleA
user.rights = [ rightA.id, rightB.id ]
user.saveAll({
 role: true,
 rights: true
})

Note: be careful that user.rights will be repopulated with rightA and rightB, but those objects will not be the same as the original rightA and rightB. That means rightA.User_id is undefined (because saveAll knows nothing about it), but user.rights[0].User_id will be set.

Tree has the same possibilities that you have in embed

pivot data

If you want to save pivot data (data you store in a belongsToMany relationship), use setPivot and getPivot

user.rights = [ rightA, rightB ]
rightA.setPivot('User', { period: 'infinity' })
rightB.setPivot('User', { period: 'this month' })
user.saveAll({ rights: true })

The data will be stored in the joint table. It is shared between the user instance and the right instance

Right
 .get('rightAId')
 .embed({ users: true })
 .then((rightA) => {
 console.log(rightA.users[0].getPivot()) // should be equal
 })
User
 .get('userId')
 .embed({ rights: true })
 .then((user) => {
 console.log(user.rights[0].getPivot()) // should be equal
 })

Note: a race condition exists here because of users[0] and rights[0]. A proper way to do it would be to use: rights.find(right => right.id === rightA.id)

Custom joins tables - three-way relationships

You can provide your own model to join tables:

User = requelize.model('User', { name: Joi.string() })
Role = requelize.model('Role', { name: Joi.string() })
Period = requelize.model('Period', { name: Joi.string() })
UserRole = requelize.model('UserRole')
// This is important (creates indexes for relation fields)
UserRole.customJoinTable('User', 'Role')
Period.hasMany('UserRole', 'userroles')
UserRole.belongsTo('Period', 'period')
User.belongsToMany('Role', 'roles', 'UserRole')
Role.belongsToMany('User', 'users', 'UserRole')

To save a three-way document:

user = new User({ name: 'John Doe' })
role = new Role({ name: 'Admin' })
period = new Period({ name: 'Infinity' })
userRole = new UserRole()
user.roles = [
 {
 // this is the related document
 document: role,
 // this is the join document
 through: userRole,
 // this will be used when saving the join document
 saveAll: { period: true }
 }
]
userRole.period = period
return user.saveAll({
 roles: true
})

To retrieve a three-way document:

User
 .embed({ roles: { _through: { period: true } } })
 .nth(0)
 .then((res) => {
 console.log(res.roles[0]._through.period)
 })

Changefeeds

requelize provide a changefeed structure with the library rxjs and Observables. You are free to use original cursors if you want (by using changes((err, cursor) => { ... }) and not .feed())

let feed = User.feed()
feed
 .filter(event => event.type === 'create')
 .subscribe(
 (event) => console.log(event),
 (err) => console.error(err)
 )

event is a simple object that contains:

  • type (string): 'create', 'update' or 'delete'
  • from (Object): the original value (null when event.type === 'create')
  • to (Object): the target value (null when event.type === 'delete')

You should unsubscribe when you do not have any use of it by using the custom Observable method close():

let feed = User.feed()
let subscription = feed
 .filter(event => event.type === 'create')
 .subscribe(
 (event) => console.log(event),
 (err) => console.error(err)
 )
somePromise()
 .then(() => {
 feed.close()
 subscription.unsubscribe()
 })

Note: in the example above, the subscription is also closed

Hooks

A few hooks are available in requelize: validating, validated, saving, saved, creating, created, updating and updated.

User.on('saving', (user) => {
 user.editedAt = new Date()
})
User.on('creating', (user) => {
 user.createdAt = new Date()
})

Hooks also support promises

User.on('saving', (user) => {
 return somePromise()
 .then(() => {
 user.foo = 'bar'
 })
})

Parse and validation

If you plan to use queries that do not resolve to a Model instance, but starts from a model, use parse() :

User
 .parse(false)
 .getAll()
 .map((user) => 1)
 .reduce((a, b) => a.add(b))
 .run()
 .then((res) => {
 assert.equal('number', typeof res)
 })

Note: you need to call run()

You can also disable validation when saving a document. Documents are only validated at insert, not at retrieval

user.someInvalidField = 'foo'
user.validate(false).save()

Virtuals

If you need virtual fields, you can use virtual method from model:

const User = requelize.model('User', {
 email: joi.string()
 firstname: joi.string(),
 lastname: joi.string()
})
User.virtual('fullname', user => `${user.firstname} ${user.lastname}`)
let user = new User({ firstname: 'John', lastname: 'Doe' })
assert.equal('John Doe', user.fullname)

Access to requelize

If you need r for any use (r.row, etc.) you can find it under requelize: requelize.r

About

RethinkDB node ORM

Topics

Resources

Code of conduct

Stars

23 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /