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

cascading-relations

v0.7.9

Published

Alternate populate/save/delete functionality for mongoose to allow for cascading relations

Downloads

15

Readme

Cascading Relations for Mongoose

This is a Mongoose plugin that adds cascading save and remove functionality for defined relationships between documents.

Rationale

I created this plugin for two reasons.

One, I found it increasingly annoying to convert populated documents back into their original form when communicating back and forth between client and server. Mongoose's populate method is awesome, but when sending back, I had to convert the populated data back to its _id.

Two, I wanted an easy way to handle actual ORM using Mongoose. Mongoose bills itself as an ORM but the only actual relationship mapping it does is with its ObjectID type and the populate method.

Usage

This plugin adds a special field to Mongoose schemas called _related. All document relationships are run through this field.

Changed functionality of populate

When you run the populate method, instead of populating by replacing the ObjectID references, it populates on the exact path but within the _related field. This gives you access to related documents while keeping the actual database fields intact for write operations. For example:

mySchema.find().populate('foo').exec(function(err, results) {
	// The "title" attribute of the related foo
	console.log(results[0]._related.foo.title); 

	// The _id field of the related foo
	console.log(results[0].foo)
});

Schema Definitions

As with the Mongoose core, related documents are specified with a combination of type:mongoose.Schema.Types.ObjectId and ref:'Related_Model'. This plugin adds two more configuration options to ObjectID types: $through and $cascadeDelete.

$through defines the path on the related document that is a reference back to this document. If you have two schema like so:

var cascadingRelations = require('cascading-relations');
var fooSchema = new mongoose.Schema({
	title:String,
	bars:[{
		type:mongoose.Schema.Types.ObjectId,
		ref:'Bar',
		$through:'foo'
	}]
});

// Apply the plugin
fooSchema.plugin(cascadingRelations);

var barSchema = new mongoose.Schema({
	title:String,
	foo:{
		type:mongoose.Schema.Types.ObjectId,
		ref:'Foo'
	}
});

// Apply the plugin
barSchema.plugin(cascadingRelations);

...then the foo property of each related bar will be populated with the _id field of the Foo document.

$cascadeDelete defines whether or not deleting a document will also delete its related documents. If this is set to true, then all related documents will be deleted when the main document is deleted. If it is false or undefined, then only the $through field of related documents will be nullified (if it's a single relationship) or the removed document's _id will be removed from the $through field (if it's a multi relationship). The related document(s) will remain in the database.

Creating Related Documents

You can create related documents in one model by using aforementioned the _related field:

var fooModel = mongoose.model('Foo')

var myFoo = new fooModel({
	title:'My Foo',
	_related:{
		bars:[
			{
				title:'My First Bar'
			},
			{
				title:'My Second Bar'
			}
		]
		single_bar:{
			title:'My Single Bar'
		}
	}
});

IMPORTANT! When you save, you need to use myFoo.cascadeSave() instead of myFoo.save(). cascadeSave() will update all reference fields on the main document and all related documents, cascade through infinite levels of related documents, and update the corresponding _related fields with the saved documents (including _id, __v, etc). Using the save() method will save using the Mongoose core - anything set in the _related field will not be saved (although it will still be accessible after the DB write operation)

Issues

Post Middleware w/ Cascade Delete

Because Mongoose still does not have callbacks implemented in its post middleware, all cascade delete operations happen behind the scenes after the callback is executed for the initial remove() call. Because of this, if you query the database immediately after running remove(), the cascade delete processes still may not have finished. In our tests, we get around this by simply waiting 5 seconds before checking if the process was successful. Keep this in mind when using this plugin - unfortunately there is nothing we can really do except for writing a custom middleware handler.

Exception Handling

Currently if saving one related document fails (for validation or another reason), it bubbles up all the way to the top and stops the saving of the original document. I'm considering adding some configuration options to ignore these issues and continue with the save process.