🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
REST query patterns
This page was created by Wikiadmin on 2026-07-29. Last edited by Wikiadmin on 2026-07-29.

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.

  1. In MDriven Designer, create a ViewModel.
  2. Right-click the ViewModel, select Add Nested ViewModel class, and choose Add Search Expressions.
  3. Add a variable for the client input. For example, use vSeekParam for a text search.
  4. Define the search expression and expose vSeekerResult as the result collection.
  5. Enable Eco.RestAllowed on the ViewModel. A REST-allowed ViewModel is available at http://<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.author

A 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.

See also