All Projects → peopledoc → django-ltree-demo

peopledoc / django-ltree-demo

Licence: MIT license
A demo for storing and querying trees in Django using PostgreSQL

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to django-ltree-demo

Laravel Nestedset
Effective tree structures in Laravel 4-5
Stars: ✭ 3,045 (+3482.35%)
Mutual labels:  hierarchical-data, trees
echarty
Minimal R/Shiny Interface to ECharts.js
Stars: ✭ 49 (-42.35%)
Mutual labels:  hierarchical-data
sf-tree-history
Tracking the history of trees in San Francisco
Stars: ✭ 23 (-72.94%)
Mutual labels:  trees
stefano-tree
Framework agnostic Nested Set (MPTT) implementation for PHP
Stars: ✭ 24 (-71.76%)
Mutual labels:  hierarchical-data
3013-Algorithms
Algorithms Course Repo
Stars: ✭ 15 (-82.35%)
Mutual labels:  trees
tree-vue
A lightweight library for handling hierarchical content. With full customizations of items rendering.
Stars: ✭ 25 (-70.59%)
Mutual labels:  hierarchical-data
Data-Structures-Algorithms-Handbook
A series of important questions with solutions to crack the coding interview and ace it!
Stars: ✭ 30 (-64.71%)
Mutual labels:  trees
icicle-chart
A partition / icicle interactive chart web component for visualizing hierarchical data
Stars: ✭ 27 (-68.24%)
Mutual labels:  hierarchical-data
React Sortable Tree
Drag-and-drop sortable component for nested data and hierarchies
Stars: ✭ 4,348 (+5015.29%)
Mutual labels:  hierarchical-data
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 (-69.41%)
Mutual labels:  hierarchical-data
finger-tree
🌵 Finger tree data structure for JavaScript
Stars: ✭ 20 (-76.47%)
Mutual labels:  trees
DSA
Data Structures and Algorithms
Stars: ✭ 13 (-84.71%)
Mutual labels:  trees
treemap-chart
A treemap interactive chart web component for visualizing hierarchical data
Stars: ✭ 27 (-68.24%)
Mutual labels:  hierarchical-data
arboles
Mapa de Arbolado Urbano
Stars: ✭ 13 (-84.71%)
Mutual labels:  trees
metacoder
Parsing, Manipulation, and Visualization of Metabarcoding/Taxonomic data
Stars: ✭ 120 (+41.18%)
Mutual labels:  trees
Storing TreeView Structures WithMongoDB
Educational repository demonstrating approaches for storing tree structures with NoSQL database MongoDB
Stars: ✭ 95 (+11.76%)
Mutual labels:  trees
silicate
A general form for complex data
Stars: ✭ 46 (-45.88%)
Mutual labels:  hierarchical-data
LeetCode
Solution to LeetCode Problems in Python and Golang 🎯
Stars: ✭ 12 (-85.88%)
Mutual labels:  trees
DSA--GeeksForGeeks
DSA course solutions in C++ Jump to below directly for more problems
Stars: ✭ 47 (-44.71%)
Mutual labels:  trees
Data-Structures-and-Algorithms
Data Structures and Algorithms implementation in Python
Stars: ✭ 31 (-63.53%)
Mutual labels:  trees

How to store trees with Django & PostgreSQL

Rationale

If you ever had the need to store hierarchical data (trees) with Django, you probably had to use a library like django-mptt or django-treebeard. Those libraries work fine at a small scale, but here at PeopleDoc we have encountered a lot of issues when using them at a bigger scale (tables with hundreds of thousands of rows and quite a lot of writings).

It turns out that storing trees in a database has been a solved problem since a long time, at least with PostgreSQL. The ltree extension provides a convenient data structure which is very fast on reads, and with almost no impact on writes. The algorithm used is very close to django-treebeard's materialized paths, but with all the power of PostgreSQL.

The main downside of using ltree is that you have to maintain the materialized path yourself. It doesn't come with any tool to do it automatically. But fortunately, it's actually quite simple to maintain this path using PostgreSQL triggers!

Integration with Django

In demo/categories/ltree.py you will find a very simple Django field for the ltree data type. This field can be used in any Django model, and adds two lookups: descendant and ancestor. Those lookups allow you to query the descendants or the ancestors of any object with a very simple SQL query.

For example, let's say you have the following model:

from django.db import models

from project.ltree import LtreeField


class Category(models.Model):
  parent = models.ForeignKey('self', null=True)
  code = models.CharField(maxlength=32, unique=True)
  path = LtreeField()

The path field represents the path from the root to the node, where each node is represented by its code (it could also be its id, but using the code is more readable when debugging). For example, if you have a genetic category, under a science category, under a top category, its path would be top.science.category.

Thanks to the descendant and ancestor lookups, the get_descendants method in django-mptt can be rewritten as:

def get_descendants(self):
    return Category.objects.filter(path__descendant=self.path)

This would generate a SQL query close to:

SELECT * FROM category WHERE path <@ 'science.biology'

The magic part: PostgreSQL triggers

If you add a ltree field to your model, you will have to keep the field up-to-date when inserting or updating instances. We could do that with Django signals, but it turns out that PostgreSQL is far better for maintaining integrity & writing efficient code.

Every time we insert or update a row, we can reconstruct its path by appending its code to the path of its parent. If the path has changed, we'll also need to update the path of the children, which can be written as a simple UPDATE query.

All that can be done easily with PostgreSQL triggers. You can find an implementation of those triggers in the file demo/categories/sql/triggers.sql.

The demo

In the demo, the following files are the most important:

How to install the demo

  • Create & activate a virtualenv
  • Install the dependencies with pip install -r requirements.txt
  • Install PostgreSQL with your favorite way
  • Export the PGHOST and PGUSER variables accordingly
  • Create the django_ltree_demo table
  • Run python manage.py migrate
  • Launch the test with pytest -v

Conclusion

With a few lines a declarative, idiomatic Django code and ~50 lines of SQL we have implemented a fast and consistent solution for storing and querying trees.

Sometimes it's good to delegate complicated data manipulation to the database instead of doing everything in Python :) .

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].