npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sequelize-embed

v2.1.1

Published

Easily insert and update sequelize models with deeply nested associations

Downloads

191

Readme

sequelize-embed

npm version Build Status dependencies Status Coverage Status Known Vulnerabilities License FOSSA Status

Easily insert and update sequelize models with deeply nested associations

While Sequelize will retrieve nested assocations via the include option, it does not provide the ability to write them. This module allows for easy synchronization of nested associations by recursively inserting new, updating existing, or deleting removed association values.

  • Synchronizes nested associations in a single atomic operation
  • Prunes redundant foreign keys and later infers them
  • Works with optimistic locking in Sequelize v4
  • Includes Epilogue middleware for document-oriented PUT/POST

API

Operations

insert(model, values, include, options)

Inserts a new record given values and synchronizes nested associations specified by include.

update(model, values, include, options)

Updates the record corresponding to values and synchronizes nested associations specified by include.

Parameters

model

The sequelize model of the root of the structure.

values

Object representing the values to be written, including any nested structure.

include

Array specifying the nested associations to be embedded. The include parameter is recursive and is usually a subset of those passed to Model.findById/One/All.

options

transaction

The transaction to be used. When provided, invoking commit or rollback is the resonsibility of the caller. Otherwise, a transaction will be created automatically and committed when done.

reload

Whether to reload and return the full instance after success. May also be an object specifying further options:

include

The nested associations to be read and returned. Defaults to the include parameter used in the write.

plain

Return plain object instead of Sequelize instances. (default true)

prune

Whether to prune redundant foreign keys. (default true)

Getting Started

Install

npm install --save sequelize-embed

Basic Example

Import sequelize-embed and initialize with sequelize:

const embed = require('sequelize-embed')(sequelize)

Setup an example schema - an Order can have Items, each of which is assigned a Department:

const Order = sequelize.define('Order', {})
const Item = sequelize.define('Item', { quantity: Sequelize.STRING })
const Department = sequelize.define('Department', { name: Sequelize.STRING })

Order.Items = Order.hasMany(Item, { as: 'items', foreignKey: 'orderId' })
Item.Department = Item.belongsTo(Department, { as: 'department', foreignKey: 'deptId' })`

Use the mkInclude helper to define the associations we wish to include. Here itemsOnly will update Items while itemsAndDept will update Items and Departments.

const { mkInclude } = embed.util.helpers

const itemsAndDept = [ mkInclude(Order.Items, mkInclude(Item.Department)) ]
const itemsOnly = [ mkInclude(Order.Items) ]

Insert an order, it's items, and departments by including itemsAndDept:

const order = {
  items: [ { quantity: 1, department: { name: 'produce' } } ]
}

embed.insert(Order, order, itemsAndDept)

// id: 1,
// items: [ { id: 1, quantity: '1', department: { id: 1, name: 'produce' } } ]

Change the quantity and department of our existing item:

const order = {
  id: 1,
  items: [ { id: 1, quantity: 2, department: { name: 'dairy' } } ]
}

embed.update(Order, order, itemsAndDept)

// id: 1,
// items: [ { id: 1, quantity: '2', department: { id: 2, name: 'dairy' } } ]

For the purposes of demonstration we've included Departments in our update, but since a Department is shared between orders we probably wouldn't want to include them when updating an order. Let's add another item, this time including just itemsOnly and being sure to specify a department known to exist:

const order = {
  id: 1,
  items: [
    { id: 1, quantity: 2, department: { id: 2, name: 'dairy' } },
    { quantity: 3, department: { id: 1 } } ]
}

embed.update(Order, order, itemsOnly, { reload: { include: itemsAndDept } })

// id: 1,
// items: [
//   { id: 1, quantity: '2', department: { id: 2, name: 'dairy' } },
//   { id: 2, quantity: '3', department: { id: 1, name: 'produce' } } ]

Notice that the new item was correctly assigned to the produce department despite Departments not being included in the update. Since belongs to foreign keys are on the source, they are always mapped back from any embedded values, even if a value isn't included for update itself. Also, we now pass itemsAndDept as the reload.include option which will include the department field in the result despite it not being updated.

Finally, remove the first item and reassign the second to the dairy department:

const order = {
  id: 1,
  items: [ { id: 2, quantity: 3, department: { id: 2 } } ]
}

embed.update(Order, order, itemsOnly, { reload: { include: itemsAndDept } })

// id: 1,
// items: [
//   { id: 2, quantity: '3', department: { id: 2, name: 'dairy' } } ]

Performance

Since the underlying data is normalized, completing an update or insert operation requires many reads and writes to synchronize the entire structure. For applications where performance is critical, be sure to restrict the total number of embedded associations and only embed those with reasonably low-cardinality.

Epilogue Middleware

Sequelize Embed also provides Epilogue middleware for automatically updating associations during PUT and POST operations. This can greatly simplify client development by giving your REST api the feel of a document-oriented database.

const embed = require('sequelize-embed')(sequelize)

const includeOnRead = ...  // include for get
const includeOnWrite = ... // include for put/post

// setup resource like normal
const resource = epilogue.resource({
  model: Model,
  include: includeOnRead,
  associations: false,
  ...
});

// add middleware to the resource, specifying includes
const middleware = embed.Epilogue(epilogue)
resource.use(middleware(includeOnWrite))

License

Everything in this repo is BSD License unless otherwise specified

sequelize-embed (c) 2017 Weston Siegenthaler

FOSSA Status