mbuhot

mbuhot

JsonApiQueryBuilder - Build Ecto Queries from JSON-API Requests

Hi all,

I’ve just published json_api_query_builder which can transform a JSON-API request with filters, fields, include, sort into an Ecto Query.

Eg:

params = %{
  "fields" => %{
    "article" => "description",
    "comment" => "body",
    "user" => "email,username"
  },
  "filter" => %{
    "articles.tag" => "animals"
  },
  "include" => "articles,articles.comments,articles.comments.user"
}

Blog.Repo.all(Blog.User.Query.build(params))

To map between the JSON-API model and the DB model, the user implements a Query module with callbacks to handle filters, field mapping, preloading relationships, etc…

defmodule Article do
  use Ecto.Schema

  schema "articles" do
    field :body, :string
    field :description, :string
    field :slug, :string
    field :tag_list, {:array, :string}
    field :title, :string
    belongs_to :author, User, foreign_key: :user_id
    has_many :comments, Comment
    timestamps()
  end

  defmodule Query do
    use JsonApiQueryBuilder,
      schema: Article,
      type: "article",
      relationships: ["author", "comments"]

    @impl JsonApiQueryBuilder
    def filter(query, "tag", value), do: from(a in query, where: ^value in a.tag_list)
    def filter(query, "comments", params) do
      comment_query = from(Comment, select: [:article_id], distinct: true) |> Comment.Query.filter(params)
      from a in query, join: c in ^subquery(comment_query), on: a.id == c.article_id
    end
    def filter(query, "author", params) do
      user_query = from(User, select: [:id]) |> User.Query.filter(params)
      from a in query, join: u in ^subquery(user_query), on: a.user_id == u.id
    end

    @impl JsonApiQueryBuilder
    def include(query, "comments", comment_params) do
      from query, preload: [comments: ^Comment.Query.build(comment_params)]
    end
    def include(query, "author", author_params) do
      from query, select_merge: [:author_id], preload: [author: ^User.Query.build(author_params)]
    end
  end
end

Links:

Hex Package
Docs
Github

Where Next?

Popular in Announcing Top

wmnnd
Hi there, for my project DBLSQD, I needed a file storage solution that is a bit more flexible than Arc. Because I thought others might f...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
wfgilman
I’ve cleaned up and open sourced three financial libraries I was using for my company. They are bindings for the APIs of these three comp...
New
sasajuric
I’d like to announce a small library called boundaries. This is an experimental project which explores the idea of enforcing boundaries ...
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 10796 134
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 14721 119
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

We're in Beta

About us Mission Statement