README.md

# FatEcto

## Description

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

Currently it's supporting following **query functions**:

- where
- select
- joins
- order_by
- include
- group_by

## Installation

#### you can get latest from github or published version from hex

```elixir
{:fat_ecto, github: "tanweerdev/fat_ecto"}
or
{:fat_ecto, "~> 0.1"}
```

#### Please do not pass custom $join type for associations which are related via has_many or many_to_many eg
```elixir
# Please dont pass join like below to avoid un-expected/duplicated records
"$include": %{"doctors" => %{"$join" => "left"}}
# correct way
"$include": %{"doctors" => %{}}
```

## Config

```elixir
config :my_app, :fat_ecto,
  repo: ExApi.Repo,
  default_limit: 10,
  max_limit: 100
```

## Usage

Once installed you can _use_ **FatEcto.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**.

```elixir
build(schema_name, params)
```

#### Example

```eliixir
defmodule MyApp.Query do
  use FatEcto.FatQuery, otp_app: :my_app, max_limit: 103, default_limit: 34
end

import MyApp.Query
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](https://hexdocs.pm/fat_ecto/) for more details.