↓ Skip to main content
A pen and ink drawing of a workshop pegboard full of hand tools above a workbench. In the middle row, four tool outlines are painted orange and empty. The four missing tools, a hammer, a screwdriver, a folding ruler and pliers, lie on a wooden tray on the bench, with a small open tin of screws tied to the tray handle by a teal cord.

Selecting Data with oslc.select in the Maximo REST API

The Maximo REST API in Practice - This article is part of a series.
Part 2: This Article
The where clause decides which records come back. oslc.select decides what each record carries: which attributes, which child objects, which related records, and under which names. This article shows every form and the JSON it returns.

The rules here come from IBM’s documentation and from our own work with the REST API, on Manage in the MAS 9.2 series. We ran every request on our test system, against IBM’s demo data, as a user without administrator rights. The examples use the object structure MXAPIASSET, which ships with Manage, and the asset 11430 at the site BEDFORD.

Without oslc.select you get links#

A query without oslc.select returns one link per record and nothing else:

curl -G "https://<your-host>/maximo/api/os/mxapiasset" \
  -H "apikey: <your-api-key>" \
  --data-urlencode 'lean=1' \
  --data-urlencode 'oslc.pageSize=20' \
  --data-urlencode 'oslc.where=siteid="BEDFORD"'
{
  "member": [
    { "href": "…/maximo/api/os/mxapiasset/_MTE0MzAvQkVERk9SRA--" },
    { "href": "…" }
  ],
  "responseInfo": {
    "href": "…",
    "nextPage": { "href": "…" },
    "pagenum": 1
  }
}

The href is the address of the record. A GET on it returns the record. For a list, one request with a select clause is far cheaper than one request per link. So every list request should carry oslc.select.

All examples use lean=1. Without it, the JSON names carry prefixes such as rdfs:member and spi:assetnum. Keep oslc.pageSize in every list request too: without it, Manage returns every matching record in one answer. Paging is the topic of the next article.

Naming attributes
#

oslc.select takes a list of attribute names, separated by commas:

oslc.select=assetnum,siteid,status,description
{
  "assetnum": "11430",
  "siteid": "BEDFORD",
  "status": "OPERATING",
  "status_description": "Operating",
  "description": "Centrifugal Pump 100GPM/60FT HD",
  "href": "…",
  "_rowstamp": "[0 0 0 0 0 39 71 119]",
  "_imagelibref": "…",
  "assetmeter_collectionref": "…",
  "assetspec_collectionref": "…"
}

Three rules surprise most people on the first day:

  • Case does not matter. ASSETNUM and SiteId select the same attributes as assetnum and siteid. The answer always uses lower case.
  • An unknown name is skipped without a word. assetnum,nosuchattr returns assetnum and a 200. The where clause refuses an unknown attribute with BMXAA8781E. The select clause stays silent, so a typo shows only as a missing property.
  • Manage adds properties you did not ask for. They are listed in the table below.
PropertyWhen it appearsWhat it is
hrefalwaysthe address of the record
_rowstampon every record that is saved in the databasethe version of the record, used when you update it
<attribute>_descriptionfor an attribute with a domain, when it has a valuethe description of the value, for example Operating
<child>_collectionreffor every child object of the object structurethe address of the child list of this record
_imagelibrefwhen the record has an imagethe address of the image

Null values are left out
#

An attribute without a value is missing from the answer. A client that reads member[0].shiftnum gets undefined, and the key is gone. _dropnulls=0 keeps it:

oslc.select=assetnum,shiftnum&_dropnulls=0
{ "assetnum": "11430", "shiftnum": null }

Use it when the client needs a stable set of keys, for example to fill table columns or to compare two records.

Child objects of the object structure
#

An object structure has a main object and child objects. MXAPIASSET has the asset and, among others, its meters in ASSETMETER. A child is selected by its name, with its attributes in braces:

oslc.select=assetnum,assetmeter{metername,lastreading,measureunitid}
{
  "assetnum": "11430",
  "assetmeter": [
    {
      "metername": "O-PRESSUR",
      "lastreading": "4,473",
      "measureunitid": "PSI",
      "href": "…"
    },
    { "metername": "…" }
  ]
}

The child arrives as an array, one entry per child record. A record without child records has no key for the child at all: an asset without meters has no assetmeter property. The braces nest, so a child of a child is written the same way: assetmeter{metername,measurement{measurementvalue,measuredate}}.

A star selects everything, and it goes deeper than it looks:

  • assetmeter{*} gives every attribute of each meter, and every child of the meter too, with all of their records. On our test asset that included each meter’s whole list of measurements.
  • oslc.select=* does the same for the whole object structure: every attribute, every child, every level.

A star is useful for a first look at an object structure. In a client, name the attributes. The answer stays small, and a new child in the object structure later changes nothing.

One related record: dot notation#

A relationship of the main object reaches data outside the object structure. A dot after the relationship name reads one attribute of the related record:

oslc.select=assetnum,location.description,location.status
{
  "assetnum": "11430",
  "location": {
    "description": "Condensate Return Pump- Centrifugal/100GPM/60FTHD",
    "status": "OPERATING",
    "status_description": "Operating"
  }
}

Every attribute of the same relationship lands in one object named after the relationship. A relationship of the related record works too, and adds one more level: location.locoper.location returns { "location": { "locoper": { "location": "BR430" } } }.

Dot notation reads the first record of the relationship. Use it for relationships that point to one record, such as the location of an asset, its item or its vendor.

When an attribute and a relationship share a name
#

The asset has an attribute location and a relationship LOCATION. With both in the select clause, the object of the relationship takes the name, and Manage renames the attribute:

oslc.select=assetnum,location,location.description
{
  "assetnum": "11430",
  "$alias_this_attr$location": "BR430",
  "location": {
    "description": "Condensate Return Pump- Centrifugal/100GPM/60FTHD"
  }
}

A client can read that name, and it is awkward. Give the attribute your own name instead, as shown in Renaming properties.

A list of related records: rel notation#

For a relationship with many records, such as the open work orders of an asset, write rel. before the relationship name and the attributes in braces:

oslc.select=assetnum,rel.openwo{wonum,status,wopriority}
{
  "assetnum": "11430",
  "openwo": [
    {
      "wonum": "1024",
      "status": "WSCH",
      "status_description": "Waiting to be Scheduled",
      "wopriority": 6
    },
    { "wonum": "…" }
  ]
}

The list arrives as an array named after the relationship, in lower case. The braces are required. rel.openwo alone is refused with BMXAA9244E, “No properties are specified for the dynamic relationship”.

Inside the braces, dot notation works again: rel.openwo{wonum,location.description} gives each work order a location object. A rel. term nests inside another rel. term as well.

Filter, sort and limit the list
#

The array has no paging. It holds every record of the relationship, and on an asset with a long history that is a lot. Three query parameters shape it. Their name is the main object, the relationship and the operation:

oslc.select=assetnum,rel.openwo{wonum,wopriority}
asset.openwo.where=status="APPR"
asset.openwo.orderBy=-wopriority
asset.openwo.limit=3

The where takes the same syntax as oslc.where. orderBy takes a + or - before each attribute. limit cuts the list after that many records. The main object comes first in lower case: asset for MXAPIASSET, workorder for MXAPIWODETAIL. Manage skips a parameter with the wrong prefix without a word: mxapiwodetail.showtasks.limit=1 returns the full list.

Only the first record
#

rel1. instead of rel. returns the first record of the relationship as one object:

oslc.select=assetnum,rel1.openwo{wonum,status}
{
  "assetnum": "11430",
  "openwo": {
    "wonum": "1024",
    "status": "WSCH",
    "status_description": "Waiting to be Scheduled"
  }
}

Together with asset.openwo.orderBy, this reads “the newest” or “the most urgent” related record in the same request.

Renaming properties
#

Two dashes after a name set the property name in the answer:

oslc.select=assetnum,location--mylocation,location.status
{
  "assetnum": "11430",
  "mylocation": "BR430",
  "location": {
    "status": "OPERATING",
    "status_description": "Operating"
  }
}

This solves the name clash from above. It also flattens dot notation. With an alias, the value of the related record lands directly on the record, and the description follows the new name:

oslc.select=assetnum,location.status--locstatus
{
  "assetnum": "11430",
  "locstatus": "OPERATING",
  "locstatus_description": "Operating"
}

That is the form to use when a client wants flat rows, for a table or a spreadsheet.

Following a link instead#

Sometimes a separate request is the better choice. Each record carries the address of its child lists, and a relationship name after the record address opens any related list:

GET /maximo/api/os/mxapiasset/{id}/assetmeter
GET /maximo/api/os/mxapiasset/{id}/openwo
GET /maximo/api/os/mxapiasset/{id}/openwo.mxapiwodetail

Each of these is a collection of its own. It takes oslc.where, oslc.select and paging, like the asset list itself. Without oslc.select it returns links only, the same as in the first section. The third form names an object structure after the relationship, so each work order comes back as an MXAPIWODETAIL record, with that structure’s child lists.

{id} is the part of the record’s href after the last slash. It is an encoded key, so take it from the href Manage returns and treat it as an opaque value.

Which form for which job
#

Which select form gives which shape in the answer Which select form gives which shape in the answer
Which select form gives which shape in the answer
You needWriteYou get
Attributes of the recordassetnum,statusproperties
A child object of the structureassetmeter{metername}an array
One value of a related recordlocation.descriptionan object
The same, flatlocation.description--locdesca property
A list of related recordsrel.openwo{wonum}an array
The first related recordrel1.openwo{wonum}an object
A long related list, paged/{record}/openwoa separate collection

Errors at a glance
#

Select clauseAnswerFix
assetnum,nosuchattr200, the unknown name is missingcheck the spelling
assetnum,rel.openwo400 BMXAA9244Eadd the attributes in braces
rel.openwo{wonum},openwo.wonum400 BMXAA9243Erename one of them with --
location,location.description200, $alias_this_attr$locationrename the attribute with --
mxapiwodetail.showtasks.limit=1200, the full liststart with the main object: workorder.showtasks.limit

BMXAA9243E names the property that clashes. Two properties of one record may never share a name, and rel.openwo and openwo.wonum both want the name openwo.

Examples
#

Each request below returned data on our test system. Each line is one query parameter.

Assets with their location, flat, for a table:

oslc.where=siteid="BEDFORD" and status="OPERATING"
oslc.select=assetnum,location--loc,location.description--locdesc

Assets with their meters and the last reading of each:

oslc.where=siteid="BEDFORD"
oslc.select=assetnum,assetmeter{metername,lastreading,lastreadingdate}

Assets with their three most urgent approved work orders:

oslc.where=siteid="BEDFORD"
oslc.select=assetnum,rel.openwo{wonum,description,wopriority}
asset.openwo.where=status="APPR"
asset.openwo.orderBy=-wopriority
asset.openwo.limit=3

One work order per asset, the first one, with its location:

oslc.where=siteid="BEDFORD"
oslc.select=assetnum,rel1.openwo{wonum,status,location.description}

What comes next
#

IBM’s own pages on selecting are the reference to keep next to this article:

The next article of the series covers sorting and paging. The series overview lists all parts. If you want help with the REST API in your own Manage, our services page shows how we work, or get in touch.

IBM and Maximo are trademarks of International Business Machines Corporation, registered in many jurisdictions worldwide.

The Maximo REST API in Practice - This article is part of a series.
Part 2: This Article