An OData v4 query parser and Ecto query builder for Elixir. Parse OData query strings or full URIs and get back Ecto queries ready to execute against your own repo.
Add ex_odata4 to your dependencies in mix.exs:
def deps do
[
{:ex_odata4, "~> 0.1.0"}
]
endTell the library which OData entity names map to your Ecto schemas in config/config.exs:
config :ex_odata4, schemas: %{
"Orders" => MyApp.Orders,
"Products" => MyApp.Products
}The key is the entity name as it appears in the OData URI. The value is the Ecto schema module.
ExOdata4.parse_uri("/Orders?$filter=Amount gt 1000&$top=25&$skip=0")
|> MyApp.Repo.all()ExOdata4.get("Orders", "$filter=Status eq 'active'&$orderby=CreatedAt desc&$top=10")
|> MyApp.Repo.all()Both functions return an %Ecto.Query{}, so you pipe it into your own repo. This means the library has no opinion about your database, connection pool, or repo configuration.
| Option | Example |
|---|---|
$filter |
$filter=Name eq 'John' |
$top |
$top=25 |
$skip |
$skip=50 |
$orderby |
$orderby=Amount desc |
| Operator | Meaning |
|---|---|
eq |
Equal |
ne |
Not equal |
gt |
Greater than |
ge |
Greater than or equal |
lt |
Less than |
le |
Less than or equal |
and |
Logical and |
or |
Logical or |
| Function | Example | Translates to |
|---|---|---|
contains |
contains(Name, 'John') |
LIKE '%John%' |
startswith |
startswith(Name, 'J') |
LIKE 'J%' |
endswith |
endswith(Email, '.com') |
LIKE '%.com' |
Functions can be combined with logical operators:
$filter=contains(Name, 'John') and Amount gt 100
$filter=startswith(Status, 'act') or endswith(Email, '.com')
- Strings:
'hello' - Integers:
42,-7 - Decimals:
3.14 - Booleans:
true,false - Null:
null - Dates:
2024-01-01 - GUIDs:
00000000-0000-0000-0000-000000000000
The following OData v4 features are not currently implemented:
$select— field projection$expand— loading related entities$count— total result count$search— free-text search
- String functions:
tolower(),toupper(),trim(),length(),substring(),concat() - Date functions:
year(),month(),day(),hour(),minute(),second() - Math functions:
round(),floor(),ceiling()
not— logical negation- Lambda operators:
any(),all()
- Navigation properties:
Orders/Customer/Name eq 'John' - Collection indexing
Contributions are welcome. Open an issue or PR on GitHub.
If a schema name is not found in your config, a descriptive error is raised:
No schema configured for "Orders".
Add it to your config.exs:
config :ex_odata4, schemas: %{
"Orders" => MyApp.Orders
}
MIT