FAT

Description

FAT provides methods for dynamically building queries depending on the parameters it receive.

Currently it's supporting following query functions:

Installation

For now, you can add directly via github

{:fat_ecto, github: "tanweerdev/fat_ecto"}

Config

config :fat_ecto, :repo,

  seed_base_path: "priv/seed/csvs/",

  base_repo: ExApi.Repo,

  query_repo: ExApi.Repo,

  default_limit: 10,

  max_limit: 100

If available in Hex, the package can be installed by adding fat_ecto to your list of dependencies in mix.exs:

def deps do

[

{:fat_ecto, "~> 0.1.0"}

]

end

Use

Once installed you can importFatEcto.FatQuery inside your module and use the build method. Which is the entry method for building every query. And also the main method for the FatEcto.FatQuery.

build(schema_name, params)

Example

import FatEcto.FatQuery
query_opts = %{
      "$select" => %{
        "$fields" => ["name", "location", "rating"],
        "fat_rooms" => ["beds", "capacity"]
      },
      "$order" => %{"id" => "$desc"},
      "$where" => %{"rating" => 4},
      "$group" => ["total_staff", "rating"],
      "$include" => %{
        "fat_doctors" => %{
          "$include" => ["fat_patients"],
          "$where" => %{"name" => "ham"},
          "$order" => %{"id" => "$desc"},
          "$join" => "$right"
        }
      },
      "$right_join" => %{
        "fat_rooms" => %{
          "$on_field" => "id",
          "$on_join_table_field" => "hospital_id",
          "$select" => ["beds", "capacity", "level"],
          "$where" => %{"incharge" => "John"},
          "$order" => %{"level" => "$asc"}
        }
      }
    }
iex> build(FatEcto.FatHospital, query_opts)
iex> #Ecto.Query<from f0 in FatEcto.FatHospital, right_join: f1 in "fat_rooms",
     on: f0.id == f1.hospital_id, right_join: f2 in assoc(f0, :fat_doctors),
     where: f0.rating == ^4 and ^true, where: f1.incharge == ^"John" and ^true,
     group_by: [f0.total_staff], group_by: [f0.rating], order_by: [asc: f1.level],
     order_by: [desc: f0.id],
     select: merge(map(f0, [:name, :location, :rating, :id, {:fat_rooms, [:beds, :capacity]}]),
     %{^:fat_rooms => map(f1, [:beds, :capacity, :level])}),
     preload: [fat_doctors: #Ecto.Query<from f0 in FatEcto.FatDoctor,
     left_join: f1 in assoc(f0, :fat_patients),
     where: f0.name == ^"ham" and ^true, order_by: [desc: f0.id],
     limit: ^10, offset: ^0, preload: [:fat_patients]>]>
Options:

These are the options supported

Option Description
$include Include the assoication model doctors
$include: :fat_patients Include the assoication patients. Which has association with doctors
$select Select the fields from hospital and rooms
$where Added the where attribute in the query
$group Added the group_by attribute in the query as a list
$order Sort the result based on the order attribute
$right_join Specify the type of join
$on_field Specify the field for join
$on_join_table_field Specify the field for join in the joining table

see docs for more details.

Where

Where include methods from Ecto.Query.API. These are the options where supports.

function Description
like matches the substring with the attribute in the database. "$like" .
notLike return result where value in the substring doesn't match. "$not_like" .
ilike matches the substring passed with the attribute in the database "$ilike" .
notILike return result where value in the substring doesn't match."$not_ilike".
lessthan fetch result where value is less than the numerical value "$lt" (also apply on non_numerical fields).
lessthanequal fetch result where value is less than equal to the numerical value "$lte" (also apply on non_numerical fields.
greaterthan fetch result where value is greater than the numerical value "$gt" (also apply on non_numerical fields.)
greaterthanequal fetch result where value is greater than equal to the numerical value "gte" (also apply on non_numerical fields.
between [] ,fetch the result wher value is between the provided attributes. "$between".
notBetween [] . fetch the result wher value is not between the provided list attributes. "$not_between".
in [] , fetch result where value is in the the provided list attributes. "$in" .
notIn [] ,fetch result where value is not in the the provided list attributes. "$not_in" .
isnil value is nil. "nil".
not isnil value is not nil. "$not_null" .

Example:

    query_ opts = %{
      "$where" => %{"designation" => %{"$ilike" => "%surge %"}}
    }

   iex> build(FatEcto.FatDoctor, query_opts)
   iex> #Ecto.Query<from f in FatEcto.FatDoctor,
    where: ilike(fragment("(?)::TEXT", f.designation), ^"%surge %") and ^true>

   query_ opts = %{
      "$where" => %{"rating" => %{"$lte" => "$total_staff"}}
    }

   iex> build(FatEcto.FatHospital, opts)
   iex> #Ecto.Query<from f in FatEcto.FatHospital,
        where: f.rating <= f.total_staff and ^true>

see docs for more info

Select

Select include fields from the models as well as from the associated models and also adds foreign key dynamically. It also select fields from the model as a list.

Example:

query_opts = %{
    "$select" => ["name", "location", "rating"],
    "$order" => %{"id" => "$desc"}
}
iex> build(FatEcto.FatHospital, query_opts)
iex> #Ecto.Query<from f in FatEcto.FatHospital, order_by: [desc: f.id],
     select: map(f, [:name, :location, :rating])>

query_ opts = %{
    "$select" => %{
      "$fields" => ["name", "location", "rating"],
      "fat_rooms" => ["beds", "capacity"]
    },
    "$where" => %{"id" => 2}
}
iex> build(FatEcto.FatHospital, query_opts)
iex> #Ecto.Query<from f in FatEcto.FatHospital, where: f.id == ^2 and ^true,
     select: map(f, [:name, :location, :rating, :id, {:fat_rooms, [:beds, :capacity]}])>

see docs for more info

Joins

Joins with another table on the type of join you passed in the params. it also supports where , select, order . Supported Join types are:

Example

query_opts = %{
      "$right_join" => %{
        "fat_rooms" => %{
          "$on_field" => "id",
          "$on_join_table_field" => "hospital_id",
          "$select" => ["beds", "capacity", "level"],
          "$where" => %{"incharge" => "John"},
          "$order" => %{"nurses" => "$asc"}
        }
      }
    }
iex> build(FatEcto.FatHospital, opts)
iex> Ecto.Query<from f0 in FatEcto.FatHospital, right_join: f1 in "fat_rooms",
     on: f0.id == f1.hospital_id, where: f1.incharge == ^"John" and ^true,
     order_by: [asc: f1.nurses],
     select: merge(f0, %{^:fat_rooms => map(f1, [:beds, :capacity, :level])})>

see docs for more info.

Order_by

order_by returns the query by sort the results as asc or desc order.

Example

query_opts = %{
      "$select" => %{
        "$fields" => ["name", "location", "rating"],
        "fat_rooms" => ["beds", "capacity"]
      },
      "$order" => %{"id" => "$desc"}
    }
    iex> build(FatEcto.FatHospital, opts)
    iex> #Ecto.Query<from f in FatEcto.FatHospital, order_by: [desc: f.id],
         select: map(f, [:name, :location, :rating, :id, {:fat_rooms, [:beds, :capacity]}])>

query_ opts = %{
      "$select" => ["name", "location", "rating"],
      "$order" => %{"id" => "$asc"}
    }
iex> build(FatEcto.FatHospital, query_opts)
iex> #Ecto.Query<from f in FatEcto.FatHospital, order_by: [asc: f.id],
     select: map(f, [:name, :location, :rating])>

see docs for more info.

Include

include has different sub methods. You can specify the where , order_by , join in the include for the associated schema.

Example

query_opts = %{
      "$include" => %{
        "fat_hospitals" => %{
          "$join" => "$right",
          "$order" => %{"id" => "$desc"},
          "$where" => %{"name" => "Saint"}
        }
      },
      "$where" => %{"name" => "John"}
    }
iex> build(FatEcto.FatDoctor, opts)
iex> #Ecto.Query<from f0 in FatEcto.FatDoctor,
     right_join: f1 in assoc(f0, :fat_hospitals),
     where: f0.name == ^"John" and ^true,
     preload: [fat_hospitals: #Ecto.Query<from f in FatEcto.FatHospital,
     where: f.name == ^"Saint" and ^true, order_by:  [desc: f.id], limit: ^10, offset: ^0>]>

see docs for more info.

Group_By

group_by Groups together rows from the schema that have the same values in the given fields. It also supports multiple group_by fields in a list.

Example

query_opts = %{
      "$inner_join" => %{
        "fat_rooms" => %{
          "$on_field" => "id",
          "$on_join_table_field" => "hospital_id",
          "$select" => ["beds", "capacity", "level"],
          "$where" => %{"incharge" => "John"}
        }
      },
      "$where" => %{"rating" => 3},
      "$group" => ["rating", "total_staff"]
    }

iex> build(FatEcto.FatHospital, query_opts)
iex> #Ecto.Query<from f0 in FatEcto.FatHospital, join: f1 in "fat_rooms",
     on: f0.id == f1.hospital_id, where: f0.rating == ^3 and ^true,
     where: f1.incharge == ^"John" and ^true, group_by: [f0.rating],
     group_by: [f0.total_staff],
     select: merge(f0, %{^:fat_rooms => map(f1, [:beds, :capacity, :level])})>

query_opts = %{
      "$select" => ["name", "location", "rating"],
      "$order" => %{"id" => "$asc"},
      "$group" => "rating"
    }

iex>  build(FatEcto.FatHospital, query_opts)
iex>  #Ecto.Query<from f in FatEcto.FatHospital, group_by: [f.rating],
      order_by: [asc: f.id], select: map(f, [:name, :location, :rating])>

see docs for more info.

Paginator

FAT allows to restrict the number of results you want to return from the repo. You can define limit as limit and offset as skip.

Example

opts = %{
      "$select" => ["name", "location", "rating"],
      "$order" => %{"id" => "$asc"},
      "$group" => "rating",
      "$limit" => 20,
      "$skip" => 0
    }

If no limit is defined then FAT automatically uses default_limit. For this to work you have to define the default_limit in fat_ecto config. see docs for more info.

Documentation

Documentation can be generated with ExDoc

and published on HexDocs. Once published, the docs can

be found at https://hexdocs.pm/fat_ecto.