OData Primer¶
OData (Open Data Protocol) is a REST-based protocol for building and consuming data APIs. This page covers the concepts you need to use traverse effectively - it is not a full OData specification.
Entity Sets¶
An entity set is a named collection of entities, analogous to a database table. In OData URLs, entity sets appear as path segments:
GET /Products -- all products
GET /Products(1) -- product with key 1
GET /Orders(10248) -- order with key 10248
GET /OrderDetails(OrderID=10248,ProductID=11) -- composite key
In traverse:
client.From("Products") // entity set
client.From("Products").Key(1) // single entity
client.From("OrderDetails").Key(map[string]any{
"OrderID": 10248, "ProductID": 11,
})
$filter Syntax¶
$filter selects entities matching a boolean expression.
Comparison operators¶
| Operator | Meaning | Example |
|---|---|---|
eq | equal | Status eq 'Active' |
ne | not equal | Status ne 'Deleted' |
lt | less than | Price lt 100 |
le | less than or equal | Price le 100 |
gt | greater than | Price gt 10 |
ge | greater than or equal | Price ge 10 |
Logical operators¶
$filter=Price gt 10 and Price lt 100
$filter=Status eq 'Active' or Status eq 'Pending'
$filter=not (Status eq 'Deleted')
String functions¶
$filter=startswith(Name,'A')
$filter=endswith(Name,'Ltd')
$filter=contains(Name,'acme')
$filter=tolower(Name) eq 'acme corp'
Arithmetic¶
Null checks¶
$select¶
Limit which fields are returned (reduces payload size):
$expand¶
Include related entities inline (avoids N+1 round trips):
GET /Orders?$expand=OrderDetails
GET /Orders?$expand=OrderDetails($select=ProductID,Quantity)
GET /Orders?$expand=Customer,OrderDetails($expand=Product)
In OData v4, $expand supports nested query options. In OData v2, expand is a flat comma-separated list.
$orderby¶
$top and $skip¶
Server-side pagination:
Prefer Paginator over manual $skip
Manual $skip can miss or duplicate records if the dataset changes between requests. Use traverse's Paginator or delta sync instead.
$count¶
GET /Products?$count=true -- include total count in response
GET /Products/$count -- return only the count
$search¶
Full-text search (service-dependent support):
ETags¶
An ETag (entity tag) is an opaque string the server returns in the ETag response header representing the current version of an entity:
W/prefix indicates a weak ETag (content-equivalent, not byte-identical)- Strong ETags have no prefix
To update or delete safely, send the last-known ETag in the If-Match header:
If the entity was modified since you fetched it, the server returns 412 Precondition Failed.
See ETag & Concurrency for traverse's ETag API.
Batch Requests¶
OData $batch lets you bundle multiple operations into a single HTTP request, reducing round trips:
A changeset within a batch is atomic: all operations succeed or all are rolled back.
See Batch Requests for traverse's batch API.
Delta Links¶
After requesting ?$deltatoken=..., the server returns only entities that changed since that token was issued:
- Modified entities appear as full entity objects
- Deleted entities appear with
@odata.removedannotation
Delta tokens let you sync incrementally without fetching the full dataset every time.
See Delta Sync for traverse's delta API.
Actions and Functions¶
Functions are read-only operations that return data:
Actions are operations with side effects:
Both can have parameters passed in the URL (functions) or request body (actions).
OData v2 vs v4 Differences¶
| Feature | OData v2 | OData v4 |
|---|---|---|
| Date format | /Date(milliseconds)/ | ISO 8601 |
| Count | $inlinecount=allpages | $count=true |
| Skip token | $skiptoken | $skiptoken or @odata.nextLink |
| Batch content type | multipart/mixed | multipart/mixed or application/json |
| Deep insert | __deferred links | inline navigation properties |
| Delta | limited | full delta link support |
traverse detects the OData version automatically from the service metadata and response headers.