I'm trying to create a call to odata webservice that would select only distinct values of some property. Is there any good example of how to do this?
Currently the OData protocol doesn't support the distinct operator, or any other operator which would help with such query (assuming you're looking for disctinct values of a primitive property on some entity). You should be able to workaround this by implementing a service operation on the server which performs such query on the underlying provider which usually has that ability. And then the client can call that service operation instead.
Note: I know this is old, but still shows up in search responses. There is now a good solution to this problem.
In OData v4, there is support for $apply, amongst other things, $apply
can be used to return a distinct set of fields from a result set.
See related discussion: Applying Distinct to ODataQuery
from the OData v4 spec,
The query option$apply
takes a sequence of set transformations, separated by forward slashes to express that they are consecutively applied, e.g. the result of each transformation is the input to the next transformation $apply is a function that requires
tl;dr;
Basically, if I have a table that has many fields, but I want to return just the distinct records of a number of specific fields the first step is to identify the distinct columns, lets call them Name
and Id
.
Simply use the $apply
function to get a distinct result set containing just the Names and Id columns with syntax like this:
http://url.to/tableresource?$apply=groupby((Name,Id))
Lets do this by example, TuberInspections
has 1000s of rows, but only a few contractors, I want to display the names of the contractors in a drop down list to use in a filtering query.
My distinct columns are ContractorName
and ContractorId
GET /odata/TuberInspections?$apply=groupby((ContractorName,ContractorId)) HTTP/1.1 Host: localhost:1230 Response: { "@odata.context": "http://localhost:1230/odata/$metadata#TuberInspections(ContractorName,ContractorId)", "value": [ { "@odata.id": null, "ContractorId": 11534, "ContractorName": "Kermit d'Frog" }, { "@odata.id": null, "ContractorId": 11539, "ContractorName": "Carlos Spicy Wiener" }, { "@odata.id": null, "ContractorId": 16827, "ContractorName": "Jen Gelfling" } ] }
If your data structure is no flat enough, there is limited OOTB support for retrieving simple nested results structures.
If his data structure is hard to consume and you have control over the API, then you should consider creating a custom Function to return the specific recordset that you desire, that is trivial exercise that has many different options available to you, but outside of the scope of this response.
This response is directed at how to query an existing OData service for distinct values, not how to modify a service to provide such information.
Currently only a single navigation path is supported with the following syntax. The above query can also be written as:
GET /odata/TuberInspections?$apply=groupby((Contractor/EntityID,Contractor/Initials)) Host: localhost:1230 Response: { "@odata.context": "http://localhost:1230/odata/$metadata#TuberInspections(Contractor(EntityID,Initials))", "@odata.count": 3, "value": [ { "@odata.id": null, "Contractor": { "@odata.id": null, "Initials": "KdF", "EntityID": 11534 } }, { "@odata.id": null, "Contractor": { "@odata.id": null, "Initials": "SW", "EntityID": 11539 } }, { "@odata.id": null, "Contractor": { "@odata.id": null, "Initials": "Jen", "EntityID": 16827 } } ] }
There are more advanced (complicated) variations to nested or stacked $apply
transformations that include returning a count of the number of unique rows that correspond to each of the distinct results.
Including a
$count
of distinct records within the group is sort of documented here System Query Option $apply - groupby and in response to OData v4 groupby with $countGroupBy supports an aggregate extension, so we can use this in the previous URL, remember to alias the projected column name.
groupby((Contractor/EntityID,Contractor/Initials),aggregate($count as Items))
the response now includes the count:
{ "@odata.id": null, "Items": 260, "Contractor": { "@odata.id": null, "Initials": "SW", "EntityID": 11539 } },
For more information please post specific questions and tag with OData-v4 and you'll find all the help you need :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With