oslc.where. It
looks like SQL, and it is a different language with its own grammar. This article shows the
grammar, what Manage accepts, and the mistakes that end in a 400.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 clause on our test system, against IBM’s demo data, as a user
without administrator rights. The examples use
the object structures MXAPIASSET and MXAPIWODETAIL, which ship with Manage.
Our product Fiedler Data Export uses this clause. When an export
reads Manage through an object structure, the condition you type on the Export page goes to Manage
as oslc.where. So this article is also the reference for that field.
Where the clause goes#
oslc.where is a query parameter of a GET request on an object structure. The other parameters
decide what each record carries and how the answer looks. This request returns the operating assets
of the site BEDFORD, three columns each:
curl -G "https://<your-host>/maximo/api/os/mxapiasset" \
-H "apikey: <your-api-key>" \
--data-urlencode 'lean=1' \
--data-urlencode 'oslc.select=assetnum,siteid,status' \
--data-urlencode 'oslc.where=siteid="BEDFORD" and status="OPERATING"'--data-urlencode matters here. The clause holds quotes, spaces, % signs and sometimes a +, and
all of them must reach Manage encoded. Every HTTP library has an equivalent, for example
URLSearchParams in JavaScript. In the rest of this article the clauses are shown unencoded, so they
are easy to read.
The shape of a term#
A clause is a list of terms joined with and. Each term is an attribute name, an operator and a
value, written without spaces:
siteid="BEDFORD" and status="OPERATING" and priority>=2Four rules decide whether Manage can read a term:
- No space around the operator.
siteid="BEDFORD"works.siteid = "BEDFORD"is refused with a parse error. A space after the attribute name tells the parser thatincomes next. - Text and dates go in double quotes. Single quotes are SQL, and the parser stops at the first one. A text value without quotes is refused too.
- Numbers and booleans have no quotes.
priority>=2,moved=0andmoved=falseall work. - Attribute names and
andignore case.SITEID="BEDFORD" AND status="OPERATING"gives the same records.
A plain attribute name must belong to the main object of the object structure. On MXAPIASSET that
is ASSET. An unknown name is refused with its own message, which names the property it could not
find.
Operators and values#
| You want | Write | Note |
|---|---|---|
| equal | status="OPERATING" | exact match for text |
| not equal | status!="OPERATING" | |
| greater, less | priority>1, priority<=3 | numbers and dates |
| a range | priority>=2 and priority<=3 | the same attribute twice |
| one of a list | status in ["OPERATING","NOT READY"] | also numbers: priority in [1,2] |
| none of a list | siteid!="[BEDFORD,BOSTON]" | needs at least two values |
| starts with | assetnum="11%" | |
| contains | description="%pump%" | |
| does not contain | status!="%OPER%" | a NOT LIKE |
| has a value | serialnum="*" | is not null |
| has no value | serialnum!="*" | is null |
The in list may hold patterns as well. assetnum in ["11%","12%"] returns the assets whose number
starts with 11 or with 12.
How text is compared#
Without a %, the = operator looks for the exact value. status="OPERATING" finds the operating
assets, and status="OPER" finds nothing. With a % at the start or the end, the value becomes a
pattern. Case played no part in any of our runs: status="operating" returned the same records as
status="OPERATING".
One exception needs care. Some attributes have the search type TEXT in Database Configuration. On our
system ASSET.DESCRIPTION is one of them. For such an attribute, description="pump" is a word search.
It found the descriptions that contain the word “pump” and left out one that contains “Pumper”.
description="%pump%" found both. So write the % signs when you mean a pattern.
Dates#
A date is an ISO 8601 text in double quotes. The time and the offset may be left out:
installdate>="2010-01-01T00:00:00-05:00"
installdate>="2010-01-01"Watch the + of a positive offset. A server decodes a raw + in a URL as a space. Then
2024-01-01T00:00:00+01:00 arrives as 2024-01-01T00:00:00 01:00, and Manage answers with
BMXAA4144E, “The date/time format is not valid”. The error message even shows the space. Encode the
sign as %2B, or let your HTTP library encode the whole clause.
The NOT IN trap#
siteid!="[BEDFORD,BOSTON]" leaves out both sites. With one value, siteid!="[BEDFORD]", Manage
compares the site with the text [BEDFORD], brackets included. No site has that name, so the clause
returns every asset, BEDFORD included. Use siteid!="BEDFORD" for one value.
IBM’s filtering page says that NOT IN only works for ALN attributes. It works for numbers as well:
priority!="[1,2]" returns the assets whose priority is neither 1 nor 2.
That clause leaves out the assets with no priority at all. != and NOT IN behave as in SQL, and an
empty value matches neither = nor !=. To keep those records, add a group for them:
(priority!="[1,2]") or (priority!="*")Related records#
A dot follows a relationship of the business object. This returns the assets whose location is operating:
location.status="OPERATING"location is the name of a relationship of ASSET, as Database Configuration lists it. The location is
not part of MXAPIASSET, and the clause still works, because a dot path can use any relationship of
the business object. A path can go further, one relationship per step, and the last part is always an
attribute.
A relationship can also be counted. _dbcount compares the number of related rows. This returns the
assets with more than one meter:
assetmeter._dbcount>1The same family has _dbsum, _dbavg, _dbmax and _dbmin after an attribute, for example
<relationship>.<attribute>._dbsum>100.
Braces filter the parents by a child of the object structure. This returns the assets that have a meter named TEMP-F:
assetmeter{metername="TEMP-F"}Inside the braces stands the child’s name in the object structure, and the terms inside follow the same rules as above.
Combining with or#
A plain or is refused. siteid="BEDFORD" or siteid="BOSTON" ends in BMXAA8744E. Manage accepts OR
in two other forms.
The first form puts each part in parentheses. Each group may hold several terms joined with and:
(siteid="BEDFORD" and priority=1) or (siteid="BOSTON")The second form is the extra parameter opmodeor=1. It joins every term of the clause with OR:
oslc.where=siteid="BEDFORD" and siteid="BOSTON"&opmodeor=1For one attribute, in is the simplest choice. siteid in ["BEDFORD","BOSTON"] returns the same
records as (siteid="BEDFORD") or (siteid="BOSTON").
Values Manage fills in for you#
Some values are replaced on the server before the query runs:
"-dfltsite-"and"-dfltorg-"become the default site and organization of the user who calls."-personid-","-userid-"and"-laborcode-"become that user’s person, user name and labor code."~OPERATING~", with tildes, is a synonym’s internal value. Manage expands it to every status whose internal value is OPERATING. Your system may have more than one, sostatus="~OPERATING~"can return more records thanstatus="OPERATING". With!=it becomes a NOT IN over all of them.
So siteid="-dfltsite-" gives each user the assets of their own default site, with one clause for
everybody.
How Manage reads a clause#
This picture follows a clause from the URL to the records, and it shows at which step each error comes:
The middle step is the key to the whole syntax. IBM’s own pages say that oslc.where maps to the
Query by Example framework, QBE for short. Each term becomes a QBE value on the business object, and
Manage writes the SQL from those values. So the clause can only say what QBE can say, and that is
why raw SQL is refused.
A savedQuery parameter in the same request is added to the clause with AND. Fiedler Data Export
uses that combination: you pick a saved query of the application, and your condition narrows it
further.
Errors at a glance#
| Clause | Answer | Fix |
|---|---|---|
siteid = "BEDFORD" | 400 BMXAA8744E | remove the spaces |
siteid='BEDFORD' | 400 BMXAA8744E | use double quotes |
siteid=BEDFORD | 400 BMXAA8744E | quote the text |
siteid="BEDFORD" or siteid="BOSTON" | 400 BMXAA8744E | use groups, in or opmodeor=1 |
foo="x" | 400 BMXAA8781E | use an attribute of the main object |
a date with a raw + | 400 BMXAA4144E | encode it as %2B |
siteid!="[BEDFORD]" | 200, every site | write siteid!="BEDFORD" |
The message of BMXAA8744E names the column where the parser stopped. That number points straight at the fault.
Examples#
Each clause below returned records on our test system. The object structure is named above each one.
Operating assets of one site (MXAPIASSET):
siteid="BEDFORD" and status="OPERATING"Assets of two sites (MXAPIASSET):
siteid in ["BEDFORD","BOSTON"]Assets without a serial number at the caller’s default site (MXAPIASSET):
serialnum!="*" and siteid="-dfltsite-"Assets at an operating location, with a TEMP-F meter (MXAPIASSET):
location.status="OPERATING" and assetmeter{metername="TEMP-F"}Approved or started work orders of priority 1 or 2 (MXAPIWODETAIL):
status in ["APPR","INPRG"] and wopriority<=2Work orders reported in 2024 (MXAPIWODETAIL):
reportdate>="2024-01-01" and reportdate<"2025-01-01"Priority 1 assets at BEDFORD, and every asset at BOSTON (MXAPIASSET):
(siteid="BEDFORD" and priority=1) or (siteid="BOSTON")What comes next#
IBM’s own pages on filtering are the reference to keep next to this article:
- Filtering in the IBM Maximo Manage documentation.
- Query (GET) / Filtering in IBM’s Maximo REST API guide on GitHub.
How Fiedler Data Export reads Manage through an object structure, and where this clause comes in, is in Two Ways to Read Manage. 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.
