Skip to content

Latest commit

 

History

History
328 lines (274 loc) · 7.63 KB

README.md

File metadata and controls

328 lines (274 loc) · 7.63 KB

Mongoose Materialized Path Build Status Test Coverage

Mongoose plugin for tree hierarchy using the materialized path pattern.

Installation

npm install mongoose-mpath

Setup

Important note

This plugins adds parent and path fields to the schema. You should not define them in the schema which the plugin is enabled on.

Semantics

MySchema.plugin(MpathPlugin, [PLUGIN OPTIONS]);

Plugin options

{
  pathSeparator: '#',              // String used to separate ids in path
  onDelete:      'REPARENT',       // 'REPARENT' or 'DELETE'
  idType:        Schema.ObjectId   // Type used for model id
}

Example setup

import Mongoose from 'mongoose';
import MpathPlugin from 'mongoose-mpath';

const LocationSchema = new Mongoose.Schema({name: String});
LocationSchema.plugin(MpathPlugin);

const LocationModel = Mongoose.model('Location', LocationSchema);

const europe = new LocationModel({name: 'europe'});
const sweden = new LocationModel({name: 'sweden', parent: europe});
const stockholm = new LocationModel({name: 'stockholm', parent: sweden});

await europe.save();
await sweden.save();
await stockholm.save();

At this point in mongoDB you will have documents similar to

{
  "_id" : ObjectId("50136e40c78c4b9403000001"),
  "name" : "europe",
  "path" : "50136e40c78c4b9403000001"
}
{
  "_id" : ObjectId("50136e40c78c4b9403000002"),
  "name" : "sweden",
  "parent" : ObjectId("50136e40c78c4b9403000001"),
  "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002"
}
{
  "_id" : ObjectId("50136e40c78c4b9403000003"),
  "name" : "stockholm",
  "parent" : ObjectId("50136e40c78c4b9403000002"),
  "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002#50136e40c78c4b9403000003"
}

The path is used for recursive methods and is kept up to date by the plugin if the parent is changed.

API

All examples below are based on the following document hierarchy:

africa
europe
 - norway
 - sweden
   -- stockholm
     --- skansen

getAncestors()

Returns ancestors of a document. Returns a promise.

Signature

document.getAncestors(conditions, [fields], [options])

Arguments

  • See offical docs on model.find() for description of arguments.

Example

const ancestors = await stockholm.getAncestors({});    // (Array) [europe, sweden]

getAllChildren()

Returns all children of a document. Returns a promise.

Signature

document.getAllChildren(conditions, [fields], [options])

Arguments

  • See offical docs on model.find() for description of arguments.

Example

const children = await sweden.getAllChildren({});       // (Array) [stockholm, skansen]
const children = await stockholm.getAllChildren({});    // (Array) [skansen]

getChildrenTree()

Returns all children of a document formatted as a tree hierarchy. Returns a promise.

Signature

document.getChildrenTree([args])    // as method
model.getChildrenTree([args])       // as static

Arguments

  • (Object) args

    {
        (Object) filters: {},            // mongoose query filters
        (Object|String) fields: null,    // mongoose query fields (null equals all fields)
        (Object) options: {},            // mongoose query options
        (String) populate: '',           // string to passed to populate()
        (int) minLevel: 1,               // minimum level to search from
        (Mongoose.document) rootDoc      // mongoose document
    }
    

    Example

    const args = {
      filters: {author: 'vikpe'},
      fields: '_id name',
      options: {sort: 'name'},
      populate: 'repos',
      minLevel: 2
    }

Example

const tree = await sweden.getChildrenTree({});
// tree is an array similar to
/*
[
  {
    'name': 'sthlm',
    'children': [
      {
        'name': 'skansen',
        'children': [],          
      }
    ],
  }
]
*/

getImmediateChildren()

Returns immediate children of a document. Returns a promise.

Signature

document.getImmediateChildren(conditions, [fields], [options])

Arguments

  • See offical docs on model.find() for description of arguments.

Example

const children = await europe.getImmediateChildren({});    // (Array) [norway, sweden]
const children = await sweden.getImmediateChildren({});    // (Array) [stockholm]

getParent()

Returns parent of a document.

Signature

document.getParent([fields], [options])

Arguments

  • See offical docs on model.find() for description of arguments.

Example

const parent = await sweden.getParent();       // (Object) europe
const parent = await stockholm.getParent();    // (Object) sweden

level

A Virtual field that equals to the level of a document in the hierarchy.

Signature

(Number) document.level

Example

africa.level    // 1
sweden.level    // 2
skansen.level   // 4

More examples

Given the following document hierarchy:

africa
europe
 - norway
 - sweden
   -- stockholm
     --- skansen

getAncestors()

europe.getAncestors()       // (Array) []
stockholm.getAncestors()    // (Array) [europe, sweden]
skansen.getAncestors()      // (Array) [europe, sweden, stockholm]

getAllChildren()

europe.getAllChildren()       // (Array) [sweden, stockholm, skansen]
stockholm.getAllChildren()    // (Array) [skansen]
skansen.getAllChildren()      // (Array) []

getImmediateChildren()

europe.getImmediateChildren()       // (Array) [norway, sweden]
stockholm.getImmediateChildren()    // (Array) [skansen]
skansen.getImmediateChildren()      // (Array) []

getChildrenTree()

europe.getChildrenTree()

/*
[
  {
    'name': 'norway',
    'children': []
  },
  {
    'name': 'sweden',
    'children': [
        {
          'name': 'sthlm',
          'children': [
            {
              'name': 'skansen',
              'children': []          
            }
          ],
        }
    ]
   }  
]
*/


sweden.getChildrenTree()

/*
[
  {
    'name': 'sthlm',
    'children': [
      {
        'name': 'skansen',
        'children': [],          
      }
    ],
  }
]
*/

getParent()

europe.getParent()       // (null)
stockholm.getParent()    // (Object) sweden
skansen.getParent()      // (Object) stockholm

level

africa.level       // (Number) 1
europe.level       // (Number) 1
norway.level       // (Number) 2
sweden.level       // (Number) 2
stockholm.level    // (Number) 3
skansen.level      // (Number) 4

Development

Feedback and pull requests are most welcome!

  1. npm install mongoose-mpath
  2. Download and install MongoDB (Community Server).
  3. Start MongoDB: mongod
  4. Run tests: npm run test

Credits

This plugin is inspired by swayf/mongoose-path-tree.