# `GraphApi.OData`
[🔗](https://github.com/keenmate/microsoft_graph/blob/v1.0.0-rc.1/lib/graph_api/odata.ex#L1)

Functional builder for OData query parameters.

Builds `$select`, `$filter`, `$expand`, `$top`, `$skip`, `$orderby`,
`$count`, and `$search` query parameters for Microsoft Graph API requests.

## Examples

    alias GraphApi.OData

    query = OData.new()
      |> OData.select(["displayName", "mail", "id"])
      |> OData.filter("department eq 'Engineering'")
      |> OData.top(25)
      |> OData.orderby("displayName")

    params = OData.to_params(query)
    # %{"$select" => "displayName,mail,id", "$filter" => "department eq 'Engineering'", ...}

The `$filter` value is a raw string — Graph filter syntax is too varied for a DSL.

# `t`

```elixir
@type t() :: %GraphApi.OData{
  count: boolean() | nil,
  expand: [String.t()] | nil,
  filter: String.t() | nil,
  orderby: String.t() | nil,
  search: String.t() | nil,
  select: [String.t()] | nil,
  skip: non_neg_integer() | nil,
  top: pos_integer() | nil
}
```

# `count`

```elixir
@spec count(t()) :: t()
```

Sets `$count` to true, requesting an inline count of matching resources.

## Examples

    OData.new() |> OData.count()

# `expand`

```elixir
@spec expand(t(), [String.t()]) :: t()
```

Sets `$expand` fields. Accepts a list of relationship names.

## Examples

    OData.new() |> OData.expand(["manager", "directReports"])

# `filter`

```elixir
@spec filter(t(), String.t() | GraphApi.OData.Filter.t()) :: t()
```

Sets the `$filter` expression.

Accepts a raw OData filter string, a `Filter` struct, or a schema module
with keyword conditions for schema-aware filtering.

## Examples

    # Raw string
    OData.new() |> OData.filter("startsWith(displayName, 'A')")

    # Schema-aware keyword syntax (equality, AND-ed)
    OData.new() |> OData.filter(User, department: "Engineering", account_enabled: true)

    # Filter builder struct
    filter = Filter.new(User) |> Filter.where(:display_name, :starts_with, "A")
    OData.new() |> OData.filter(filter)

# `filter`

```elixir
@spec filter(t(), module(), keyword()) :: t()
```

Sets the `$filter` expression using a schema module and keyword conditions.

Each keyword is a snake_case field name from the schema, matched with `eq`.
Multiple conditions are combined with `and`.

## Examples

    alias GraphApi.Schema.User

    OData.new()
    |> OData.filter(User, department: "Engineering", account_enabled: true)
    # => $filter=department eq 'Engineering' and accountEnabled eq true

# `new`

```elixir
@spec new() :: t()
```

Creates a new empty OData query builder.

# `orderby`

```elixir
@spec orderby(t(), String.t()) :: t()
```

Sets `$orderby` expression.

## Examples

    OData.new() |> OData.orderby("displayName desc")

# `search`

```elixir
@spec search(t(), String.t()) :: t()
```

Sets `$search` expression.

## Examples

    OData.new() |> OData.search(""displayName:John"")

# `select`

```elixir
@spec select(t(), [String.t()]) :: t()
```

Sets `$select` fields. Accepts a list of field name strings.

## Examples

    OData.new() |> OData.select(["displayName", "mail"])

# `skip`

```elixir
@spec skip(t(), non_neg_integer()) :: t()
```

Sets `$skip` (offset). Must be a non-negative integer.

## Examples

    OData.new() |> OData.skip(50)

# `to_params`

```elixir
@spec to_params(t()) :: map()
```

Converts the OData query builder to a map of query parameters.

Only includes parameters that have been set (non-nil).
Lists are joined with commas. Booleans are converted to strings.

## Examples

    OData.new()
    |> OData.select(["id", "displayName"])
    |> OData.top(10)
    |> OData.to_params()
    #=> %{"$select" => "id,displayName", "$top" => "10"}

# `top`

```elixir
@spec top(t(), pos_integer()) :: t()
```

Sets `$top` (page size). Must be a positive integer.

## Examples

    OData.new() |> OData.top(25)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
