All Projects → Byzanteam-Labs → hierarch

Byzanteam-Labs / hierarch

Licence: MIT license
Tree structure & hierarchy for ecto models with ltree(Postgres)

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to hierarch

ex operation
A library for making domain operations in Elixir
Stars: ✭ 33 (+10%)
Mutual labels:  ecto
JMind
基于 Canvas 技术,使用 Janvas 封装库实现的 XMind 的核心功能
Stars: ✭ 274 (+813.33%)
Mutual labels:  hierarchy
contextual
🌈 Generate your Ecto contexts using this macro and eliminate boilerplate
Stars: ✭ 18 (-40%)
Mutual labels:  ecto
algoliax
Algolia integration to elixir application
Stars: ✭ 38 (+26.67%)
Mutual labels:  ecto
wp-user-parents
Allow users to delegate control of their accounts to other users
Stars: ✭ 14 (-53.33%)
Mutual labels:  hierarchy
ogrep-rs
Outline grep — search in indentation-structured texts (Rust version)
Stars: ✭ 32 (+6.67%)
Mutual labels:  hierarchy
MultiplatformPlayground
Kotlin Multiplatform project in Jetpack Compose & SwiftUI with shared ViewModel layer and File upload
Stars: ✭ 72 (+140%)
Mutual labels:  hierarchy
multi-ctx
Multiple Spring Contexts Showcase
Stars: ✭ 16 (-46.67%)
Mutual labels:  hierarchy
ecto profiler
Project for Ecto DB profiling
Stars: ✭ 16 (-46.67%)
Mutual labels:  ecto
ecto trail
EctoTrail allows to store Ecto changeset changes in a separate audit_log table.
Stars: ✭ 51 (+70%)
Mutual labels:  ecto
phoenix pagination
Simple pagination for Ecto and Phoenix that uses plain EEx templates.
Stars: ✭ 20 (-33.33%)
Mutual labels:  ecto
querie
Compose Ecto query from the client side
Stars: ✭ 20 (-33.33%)
Mutual labels:  ecto
ectograph
Ectograph is a set of utility functions for using Ecto in combination with graphql-elixir/graphql
Stars: ✭ 29 (-3.33%)
Mutual labels:  ecto
strong migrations
Catch unsafe migrations in your Elixir application
Stars: ✭ 58 (+93.33%)
Mutual labels:  ecto
monetized
A lightweight solution for handling and storing money.
Stars: ✭ 46 (+53.33%)
Mutual labels:  ecto
JSON-path
Find the path of a key / value in a JSON hierarchy easily.
Stars: ✭ 88 (+193.33%)
Mutual labels:  hierarchy
music db
A playground for Ecto using a simple music database
Stars: ✭ 29 (-3.33%)
Mutual labels:  ecto
ecto nested changeset
Helpers for manipulating nested Ecto changesets
Stars: ✭ 23 (-23.33%)
Mutual labels:  ecto
elixir-revisionair ecto
A Revisionair adapter based on Ecto. Allows you to persist and keep track of revisions of your data structures in any of Ecto's supported databases.
Stars: ✭ 18 (-40%)
Mutual labels:  ecto
mongodb ecto
MongoDB adapter for Ecto
Stars: ✭ 348 (+1060%)
Mutual labels:  ecto

Hierarch

Elixir CI Hex.pm Hex docs

Hierarch helps you to build tree structure(hierarchy) for ecto models with ltree(Postgres).

Installation

Add hierarch to your list of dependencies in mix.exs:

def deps do
  [
    {:hierarch, "~> 0.2.1"}
  ]
end

Enable ltree extension:

execute "CREATE EXTENSION IF NOT EXISTS ltree"

Add GIST index:

create index(:catelogs, [:path], using: "GIST")

Example

Set types at config/config.exs or your environment config file

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  types: Hierarch.Postgrex.Types

Write a migration for this functionality

defmodule MyApp.Repo.Migrations.CreateCatelogs do
  use Ecto.Migration

  def change do
    execute "CREATE EXTENSION IF NOT EXISTS ltree" # Enables Ltree action

    create table(:catelogs, primary_key: false) do
      add :id, :uuid, primary_key: true # the primary key is UUID
      add :name, :string
      add :path, :ltree

      timestamps()
    end

    create index(:catelogs, [:path], using: "GIST") # Add GIST index to query
  end
end

Use Hierarch in your schema

Options:

  • path_column (default: :path): the name of the database column which stores hierarchy data;
defmodule MyApp.Catelog do
  use Ecto.Schema
  use Hierarch

  @primary_key {:id, :binary_id, autogenerate: true}

  schema "catelogs" do
    field :name, :string
    field :path, Hierarch.Ecto.UUIDLTree # Set to `UUIDLTree` if the path is ltree type

    timestamps()
  end
end

🔢Use Hierarch with bigint or integer primary key, and custom path_column

defmodule MyApp.Repo.Migrations.CreateOrganizations do
  use Ecto.Migration

  def change do
    execute "CREATE EXTENSION IF NOT EXISTS ltree" # Enables Ltree action

    create table(:organizations) do
      add :name, :string
      add :ancestry, :ltree, null: false, default: ""
    end

    create index(:organizations, [:ancestry], using: "GIST")
  end
end
defmodule MyApp.Organization do
  @moduledoc false
  use Ecto.Schema
  use Hierarch, path_column: :ancestry # set path_column

  schema "organizations" do
    field :name, :string
    field :ancestry, Hierarch.Ecto.LTree # Use LTree for bigint or integer primary key
  end
end

Usage

build_child_of/2

Take the parent struct and attributes struct, return a child struct.

parent = %Catelog{
  id: "570526aa-e2f3-49a7-870a-c150d3bf6ac9",
  name: "Top",
  path: ""
}
catelog = Catelog.build_child_of(parent, %{name: "Top.Science"})
#  %Catelog{
#    id: nil,
#    name: "Top.Science",
#    path: "570526aa-e2f3-49a7-870a-c150d3bf6ac9"
#  }

is_root?/1

Detect a struct whether a root.

catelog = %Catelog{
  id: "570526aa-e2f3-49a7-870a-c150d3bf6ac9",
  name: "Top",
  path: ""
}
Catelog.is_root?(catelog) # true

parent/1

Return the parent query expression of the given struct, return nil if it is the root.

catelog = %Catelog{
  id: "570526aa-e2f3-49a7-870a-c150d3bf6ac9",
  name: "Top",
  path: ""
}
Catelog.parent(catelog) |> Repo.one # nil

root/1

Return the root query expression of the given struct, return itself if it is the root.

catelog = %Catelog{
  id: "570526aa-e2f3-49a7-870a-c150d3bf6ac9",
  name: "Top",
  path: ""
}
Catelog.root(catelog) |> Repo.one # return itself `catelog`

ancestors/2

Return the ancestors query expression of the given struct. Options:

  • :with_self - when true to include itself. Defaults to false
catelog = %Catelog{
  id: "06a84054-8827-42c2-9b75-25ed75e6d5f8",
  name: "Top.Hobbies",
  path: "a9ae8f40-b016-4bf9-8224-e2755466e699",
}
Catelog.ancestors(catelog) |> Repo.all
#  [%Catelog{
#    id: "a9ae8f40-b016-4bf9-8224-e2755466e699",
#    name: "Top",
#    path: ""
#  }]

Catelog.ancestors(catelog, with_self: true) |> Repo.all
#  [
#    %Catelog{
#      id: "a9ae8f40-b016-4bf9-8224-e2755466e699",
#      name: "Top",
#      path: ""
#    },
#    %Catelog{
#      id: "06a84054-8827-42c2-9b75-25ed75e6d5f8",
#      name: "Top.Hobbies",
#      path: "a9ae8f40-b016-4bf9-8224-e2755466e699"
#    }
#  ]

descendants/2

Return the descendants query expression of the given struct. Options:

  • :with_self - when true to include itself. Defaults to false
catelog = %Catelog{
  id: "06a84054-8827-42c2-9b75-25ed75e6d5f8",
  name: "Top.Hobbies",
  path: "a9ae8f40-b016-4bf9-8224-e2755466e699",
}
Catelog.descendants(catelog) |> Repo.all
#  [
#    %Catelog{
#      id: "6ff8db2e-5c01-4e82-a25b-4c1568df1efb",
#      name: "Top.Hobbies.Amateurs_Astronomy",
#      path: "a9ae8f40-b016-4bf9-8224-e2755466e699.06a84054-8827-42c2-9b75-25ed75e6d5f8"
#    }
#  ]

siblings/2

Return the siblings query expression of the given struct. Options:

  • :with_self - when true to include itself. Defaults to false
catelog = %Catelog{
  id: "06a84054-8827-42c2-9b75-25ed75e6d5f8",
  name: "Top.Hobbies",
  path: "a9ae8f40-b016-4bf9-8224-e2755466e699",
}
Catelog.siblings(catelog) |> Repo.all
#  [
#    %Catelog{
#      id: "6c11f83f-3c3c-44bf-9940-8153c1f04de9",
#      name: "Top.Science",
#      path: "a9ae8f40-b016-4bf9-8224-e2755466e699"
#    },
#    %Catelog{
#      id: "570526aa-e2f3-49a7-870a-c150d3bf6ac9",
#      name: "Top.Collections",
#      path: "a9ae8f40-b016-4bf9-8224-e2755466e699"
#    }
#  ]

roots/0

Return the roots query expression.

Catelog.roots() |> Repo.all
#  [
#    %Catelog{
#      id: "a9ae8f40-b016-4bf9-8224-e2755466e699",
#      name: "Top",
#      path: ""
#    }
#  ]

Contributing

First, set appropriate settings for test database.

export POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres MIX_ENV=test

docker-compose up

mix do ecto.create, ecto.migrate

run test.

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