Package for sorting ecto query

EctoJuno is a package that provides parsing, validation and applying sorting parameters for your ecto queries on models. Currently sorting by joint query is not implemented, as well as custom validators for your parameters. Also you need elixir 1.14 to use this package. Hope this package will help someone not just me ). Looking for a feedback, so if you have any thoughts, please share.

Below is a sample usage of library (assuming you have User ecto schema and Repo module):

alias EctoJuno.Query.Sorting

def list_sorted_users_for_admin(params) do
 User
 |> Sorting.sort_query(User, params)
 |> Repo.all()
end

def list_sorted_users_for_manager(params) do
 User
 |> Sorting.sort_query([:id, :inserted_at], params)
 |> Repo.all()
end
2 Likes

Released v0.2.0 version in which added sorting by joint query.
Let’s assume you have User and Post schemas, Repo module. And users has many posts. If you need sort users by post’s titles than your code will look like:

alias EctoJuno.Query.Sorting

def sort_users_by_posts do
 params = %{"sort_by" => "title", "sort_direction" => "desc"}

 User
 |> join(:left, [u], p in assoc(u, :posts), as: :posts)
 |> Sorting.sort_query(User, params, :posts)
 |> Repo.all()
end

In the next version there’ll be sorting templates: you can define which schema and or binding will be used based on sorting field you passing by

Released custom schema pickup based on provided sort_by field feature.

Example template definition:

defmodule Sample.UserSorting do
 use EctoJuno.Query.SortingTemplate

  def prepare_sorting_params("post_" <> field) do
   {Post, field, :posts}
  end

  def prepare_sorting_params(nil) do
   {User, "inserted_at"}
  end

  def prepare_sorting_params(field) do
   {User, field}
  end
end

Example usage:

# Sort by post's title column
User
|> join(:left, [u], p in assoc(u, :posts), as: :posts)
|> UserSorting.sort_query(%{sort_by: "post_title", sort_direction: "desc"})
|> Repo.all()

# Sort by user's age column
User
|> join(:left, [u], p in assoc(u, :posts), as: :posts)
|> UserSorting.sort_query(%{sort_by: "age", sort_direction: "desc"})
|> Repo.all()