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.
ASSETNUMandSiteIdselect the same attributes asassetnumandsiteid. The answer always uses lower case. - An unknown name is skipped without a word.
assetnum,nosuchattrreturnsassetnumand 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.
| Property | When it appears | What it is |
|---|---|---|
href | always | the address of the record |
_rowstamp | on every record that is saved in the database | the version of the record, used when you update it |
<attribute>_description | for an attribute with a domain, when it has a value | the description of the value, for example Operating |
<child>_collectionref | for every child object of the object structure | the address of the child list of this record |
_imagelibref | when the record has an image | the 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=3The 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.mxapiwodetailEach 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#
| You need | Write | You get |
|---|---|---|
| Attributes of the record | assetnum,status | properties |
| A child object of the structure | assetmeter{metername} | an array |
| One value of a related record | location.description | an object |
| The same, flat | location.description--locdesc | a property |
| A list of related records | rel.openwo{wonum} | an array |
| The first related record | rel1.openwo{wonum} | an object |
| A long related list, paged | /{record}/openwo | a separate collection |
Errors at a glance#
| Select clause | Answer | Fix |
|---|---|---|
assetnum,nosuchattr | 200, the unknown name is missing | check the spelling |
assetnum,rel.openwo | 400 BMXAA9244E | add the attributes in braces |
rel.openwo{wonum},openwo.wonum | 400 BMXAA9243E | rename one of them with -- |
location,location.description | 200, $alias_this_attr$location | rename the attribute with -- |
mxapiwodetail.showtasks.limit=1 | 200, the full list | start 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--locdescAssets 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=3One 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:
- Selecting in the IBM Maximo Manage documentation.
- Query (GET) / Selecting in IBM’s Maximo REST API guide on GitHub.
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.
