All Projects → caaatisgood → mongodb-tree-structure

caaatisgood / mongodb-tree-structure

Licence: other
Implementing Tree Structure in MongoDB

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to mongodb-tree-structure

Wmderland
🌳 X11 tiling window manager using space partitioning trees
Stars: ✭ 341 (+2335.71%)
Mutual labels:  tree, tree-structure
Buckets Js
A complete, fully tested and documented data structure library written in pure JavaScript.
Stars: ✭ 1,128 (+7957.14%)
Mutual labels:  tree, tree-structure
Bosket
Collection of tree view components for front-end frameworks. 🌳
Stars: ✭ 457 (+3164.29%)
Mutual labels:  tree, tree-structure
prune
A tree library for Java 8 with functional sensibilities.
Stars: ✭ 22 (+57.14%)
Mutual labels:  tree, tree-structure
Array To Tree
Convert a plain array of nodes (with pointers to parent nodes) to a nested data structure
Stars: ✭ 141 (+907.14%)
Mutual labels:  tree, tree-structure
react-treefold
A renderless tree component for your hierarchical React views
Stars: ✭ 37 (+164.29%)
Mutual labels:  tree, tree-structure
Ki
Go language (golang) full strength tree structures (ki in Japanese)
Stars: ✭ 61 (+335.71%)
Mutual labels:  tree, tree-structure
react-tree
Hierarchical tree component for React in Typescript
Stars: ✭ 174 (+1142.86%)
Mutual labels:  tree, tree-structure
Containers
This library provides various containers. Each container has utility functions to manipulate the data it holds. This is an abstraction as to not have to manually manage and reallocate memory.
Stars: ✭ 125 (+792.86%)
Mutual labels:  tree, tree-structure
Bplustree
A minimal but extreme fast B+ tree indexing structure demo for billions of key-value storage
Stars: ✭ 1,598 (+11314.29%)
Mutual labels:  tree, tree-structure
stefano-tree
Framework agnostic Nested Set (MPTT) implementation for PHP
Stars: ✭ 24 (+71.43%)
Mutual labels:  tree, tree-structure
Relation Classification Using Bidirectional Lstm Tree
TensorFlow Implementation of the paper "End-to-End Relation Extraction using LSTMs on Sequences and Tree Structures" and "Classifying Relations via Long Short Term Memory Networks along Shortest Dependency Paths" for classifying relations
Stars: ✭ 167 (+1092.86%)
Mutual labels:  tree, tree-structure
treetime
TreeTime is a data organisation, management and analysis tool. A tree is a hierarchical structure that arranges information in units and sub-units. TreeTime uses linked trees (one data item can be part of different distinct trees) to store and organise any general purpose data.
Stars: ✭ 26 (+85.71%)
Mutual labels:  tree, tree-structure
tree-json-generator
Simple JavaScript Tree Generator library
Stars: ✭ 13 (-7.14%)
Mutual labels:  tree, tree-structure
TreeRep
Learning Tree structures and Tree metrics
Stars: ✭ 18 (+28.57%)
Mutual labels:  tree, tree-structure
Angular2 Tree Diagram
Angular Hierarchical UI module
Stars: ✭ 50 (+257.14%)
Mutual labels:  tree, tree-structure
vue-virtualised
Blazing fast scrolling and updating for any amount of list and hierarchical data.
Stars: ✭ 18 (+28.57%)
Mutual labels:  tree, tree-structure
performant-array-to-tree
Converts an array of items with ids and parent ids to a nested tree in a performant O(n) way. Runs in browsers and Node.js.
Stars: ✭ 193 (+1278.57%)
Mutual labels:  tree, tree-structure
Abp.generaltree
For Abp vNext
Stars: ✭ 106 (+657.14%)
Mutual labels:  tree, tree-structure
Graphview
Flutter GraphView is used to display data in graph structures. It can display Tree layout, Directed and Layered graph. Useful for Family Tree, Hierarchy View.
Stars: ✭ 152 (+985.71%)
Mutual labels:  tree, tree-structure

Implementing Tree Structure in MongoDB

A way to implement tree structure with one MongoDB collection. Showing some basic ideas of schema design and CRUD concepts. Using mongoose and normalizr in example code.

[Warning]

This is just a way to implement tree structure from my very little experience. It may not be the best choice for your case.

Feel free to hit me up with issue or pr if you have any advice.

Schema

Each document represents a tree node. It has "parent", "children" and "ancestors" field to save document id (provided by MongoDB) respectively as node reference.

Normally, you need to have one document to be the top node(or "Root") of your tree structure. Each node must refer to one any other nodes as their parent node, except the top node. A node can have zero to many child node. The "ancestors" holds all of the ancestor nodes' reference from top node all the way down to its parent node.

// schema.js
import mongoose from 'mongoose'

const Schema = mongoose.Schema

const treeSchema = new Schema({
  parent: {
    type: Schema.Types.ObjectId,
    ref: 'Node'
  },
  children: [{
    type: Schema.Types.ObjectId,
    ref: 'Node'
  }],
  ancestors: [{
    type: Schema.Types.ObjectId,
    ref: 'Node'
  }]
})

export default mongoose.model('Node', treeSchema)

CRUD

Create

Creating a tree node

  1. Find parent node document to get the "ancestors" for our new node.
  2. Save the id of parent node and ancestor nodes when adding a new node.
  3. Add the id of the new node to the parent node's children field.
import Node from './schema'

async function create() {

  try {
  
    const parentNode = await Node.findOne({ _id: '<PARENT_NODE_ID>' })

    const node = new Node({
      parent: parentNode._id,
      ancestors: parentNode.parent.concat(parentNode._id)
    })
    
    const newNode = await node.save()

    await Node.update({ _id: parentNode._id }, {
      $push: { children: newNode._id }
    }).exec()

    return newNode

  } catch (e) {
    // error handling
  }

}

Retrieve

To retrieve all of the nodes is easy. But it might make less sense than retrieving the whole tree (or subtree) structure and make it like some kind of nested JSON object. So let's do this!🤘

Retrieving a tree

Here's a light and simple way to carry out:

  1. Retrieve nodes from MongoDB
  2. Use normalizr to make the query result of all nodes into id(key)->document(value) object. So that we can retrieve each node with its object id.
  3. Use recursive function to trace through every nodes and build up the tree structure.
import Node from './schema'
import { normalize, Schema, arrayOf } from 'normalizr'

async function getTree() {

  try {

    // Get all nodes if you need to retrieve the whole tree
    let nodes = await Node.find()
    // or you only need the subtree of the node you specified
    // let nodes = await Node.find({ $or: [{ _id: '<NODE_ID>' }, { ancestors: '<NODE_ID>'}] })

    // Define normalizr schema
    const nodeSchema = new Schema('nodes', { idAttribute: '_id' })

    // Normalize the nodes that were retrieved from MongoDB
    const normalized = normalize(nodes, arrayOf(nodeSchema))

    // Normalized nodes. It's a JSON object with document id as
    // key and document as value. You can get a document directly
    // by its id (e.g. nodes['<DOCUMENT_ID>'])
    nodes = normalized.entities.nodes

    // The result property of normalized data is an array that
    // holds all the id of each document. We don't need it in
    // this example. But it might be useful if you need to map
    // through the documents before building the tree.
    const ids = normalized.result

    // The recursive function to build the tree
    const makeTree = id => {
      return Object.assign({}, nodes[id], {
        children: nodes[id].children.map(makeTree)
      })
    }

    return makeTree('<NODE_ID>')
    
  } catch (e) {
    // err handling
  }

}

// you can also add "parent": node.[node[id].parent]
// to the return object of the recursive function if  
// you want the populated result of each node's
// parent field.

Update

Moving a tree

import Node from './schema'

async function update() {

  try {

    const node = await Node.findOne({ _id: '<NODE_ID>' })
  
    // Remove node from parent's children field
    Node.update({ _id: node.parent }, {
      $pull: { children: node._id }
    }).exec()
  
    // Add node to new parent node's children field
    Node.update({ _id: '<NEW_PARENT_NODE_ID>' }, {
      $push: { children: node._id }
    }).exec()
  
    // Change node's parent
    Node.update({ _id: node._id }, {
      parent: '<NEW_PARENT_NODE_ID>'
    }).exec()
    
  } catch (e) {
    // err handling
  }

}

Delete

Removing a tree

import Node from './schema'

async function remove() {
  
  try {

    // Find the target node
    const node = await Node.find({ _id: '<NODE_ID>' })

    // Remove node from its parent's children field
    Node.update({ _id: node.parent }, {
      $pull: { children: node._id }
    }).exec()

    // Remove all subnodes of the target node
    Node.remove({
      ancestors: node._id
    }).exec()

    // Remove the target node
    Node.remove({
      _id: node._id
    })

    // return 

  } catch(e) {
    // err handling
  }

}

That's it! :octocat:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].