You can build REST endpoints for list and search use cases by exposing a predefined ViewModel and implementing its query logic with a seeker; this page is for REST clients that need filtering, ordering, and pagination.
Query model
A REST endpoint is a ViewModel that you explicitly expose. The endpoint returns the data and performs the actions that the ViewModel defines. Design one ViewModel for each client use case rather than expecting a client to submit arbitrary database queries.
For example, create an ArticleSeekerViewModel for an article list. Add a search parameter such as vSeekParam, a search expression that uses that parameter, and a vSeekerResult collection for the rows returned to the client. Expose the ViewModel as REST-allowed.
OData is not described as a supported query protocol here. Do not assume that OData query options such as $filter, $orderby, or $skip are interpreted by a REST endpoint. Define the accepted ViewModel variables and query behavior as part of each endpoint contract.
Build a filterable list endpoint
Use a seeker when the client must find a subset of a large database. A seeker translates OCLps search expressions to SQL so that the database evaluates the search instead of loading all objects into memory.
- In MDriven Designer, create a ViewModel.
- Right-click the ViewModel, select Add Nested ViewModel class, and choose Add Search Expressions.
- Add a variable for the client input. For example, use
vSeekParamfor a text search. - Define the search expression and expose
vSeekerResultas the result collection. - Enable
Eco.RestAllowedon the ViewModel. A REST-allowed ViewModel is available athttp://<host>/Rest/<ViewModelName>/.
For example, an article seeker can accept vSeekParam=green and return article rows whose configured search expression matches green. The request targets the named seeker ViewModel and supplies the variable that the ViewModel was designed to accept.
Filter by a typed value
Use a variable with the correct type when the filter is not text. For a date filter, define vAfterDate as DateTime and use it in the seeker expression:
Person.allInstances->select(p|p.Registrered>=vAfterDate)->orderBy(p|p.Registrered)This example returns Persons registered on or after vAfterDate and orders the result by Registrered. A date value must be passed as a date value, not as text.
Sort the complete result set
Ordering is separate from filtering. When a REST endpoint returns only part of a result set, do not sort only the rows already returned to the client. Requesting a different sort order requires the database search to run again so that the returned rows represent the correctly ordered full result set.
Use orderBy or orderDescending in the seeker logic.
For example, the date seeker above performs filtering and ordering in the same database query. If the client needs a different order, provide a defined ordering criterion in the ViewModel and rerun the seeker with that criterion.
Page search results
Use search result pages when a seeker result does not fit within MaxFetch. MaxFetch controls the maximum number of records returned.
The paging seeker uses these variables:
| Variable | Purpose | Example |
|---|---|---|
vSeekerResultCount
|
Total number of database hits. | A search finds 245 matching Persons. |
vSeekerPageLength
|
Number of rows per page. | Set to 25 to return 25 rows per page. |
vSeekerPageCount
|
Number of available pages. | 245 results with a page length of 25 produce the page count. |
vSeekerPage
|
Page to fetch, between 1 and the available page count. | Set to 2 before the search to fetch page 2. |
Keep filtering and ordering server-side when paging is server-side; otherwise the client sorts only an incomplete result set.
Shape the JSON response
Expose only the fields that the client needs through the ViewModel.
For example, a JSON template can expose an article as:
title : self.title
publishedAt : self.publishedAt
content : self.content
author : 'By ' + self.authorA computed column returns its computed value. In this example, author returns By followed by the author value. Keep fields as direct mappings, such as title : self.title, when the endpoint requires clean PATCH behavior.
