How to use AssetQuery to query assets via HTTP API

I’ve been looking through the Swagger, but it doesn’t seem to say what’s required for a query, what’s not, and what individual entries in the JSON actually mean. I haven’t been able to find any detailed documentation on the HTTP API either; I keep getting referred to the Swagger!

The request I think I’m supposed to use is POST /asset/query, and I’ve been trying to POST things like:

{
    "names": [
        {
            "match": "equals",
            "caseSensitive": true,
            "value": "the name of the asset",
            "negate": false
        }
    ],
    "realm": { "name": "master" },
    "types": [ "ThingAsset" ]
}

but I keep getting back a 500 along with a log message indicating that there’s a predicateType missing. But I have no clue what one of those is, nor why I need it. (I’ve also tried more terse queries, e.g. omitting the realm, types and everything but the value in the names object.)

Is there some documentation or a set of examples somewhere that I’ve not come across? Am I being naive about how to use the request?

1 Like

I have exactly the same problem! Would be also very about an answer.

Hi guys,

This is something we do really need to improve; unfortunately we use a self generated fully typesafe typescript axios client for querying our HTTP API via javascript and this has made us a bit lazy on documenting the API.

We should look to have better examples in Swagger and ideally links out to JSONSchema and/or javadoc.

Indeed the POST /asset/query endpoint takes an AssetQuery object in JSON representation; the best way to see what is possible is to start at this class and navigate through the object model.

The predicateType error you are seeing is related to the names predicate array you have defined. Although the type is known (StringPredicate) the deserialiser (Jackson) needs the predicateType field to know what sub class of ValuePredicate the json represents.

Another error is the match field which should be of type AssetQuery.Match so to fix would be:

{
    "names": [
        {
            "match": "EXACT",
            "caseSensitive": true,
            "value": "the name of the asset",
            "negate": false,
            "predicateType": "string"
        }
    ],
    "realm": { "name": "master" },
    "types": [ "ThingAsset" ]
}
3 Likes

Outstanding! Many thanks, that works. :smiley:

Out of curiosity, how come predicateType is not listed as an attribute of the object in the names list in the Swagger JSON for /asset/query?

Also, I’ve just realised that sometimes, "string" in the JSON should be replaced with a particular string such as "EXACT" but sometimes should literally be "string"! I probably wouldn’t have guessed that very quickly.

1 Like

Hi @Rich, thanks for your answer!
I would like to go one step further, I am searching for an asset which has a specific value within an attribute. In the following you find my query so far. It looks for the name of an attribute, but I see no possibility to pass the value of the desired attribute. The swagger example only shows "value": { "predicateType": "string" }. Maybe also you know how to solve this @rmwiseman ?

{
  "realm": {
    "name": "master"
  },
  "attributes": {
    "items": [
      {
        "name": {
          "match": "EXACT",
          "value": "meter_number",
          "predicateType": "string"
        }
      }
    ]
  }
}

Attributes field takes a LogicGroup<AttributePredicate>; LogicGroups allow for AND/OR logic operations with grouping (hence the name) this allows things like:

OR(AND(Attribute1Value1, Attribute2Value1), AND(Attribute1Value2, Attribute2Value2))

Which would look something like this in code:

(Attribute1Value1 && Attribute2Value1) || (Attribute1Value2, Attribute2Value2)

In your case if you’re only interested in one Attribute then you are on the right track, just need to add the value predicate the list of value predicates can be found at the top of ValuePredicate.java; so for example if it’s a boolean attribute and you want to find assets with a true value:

{
  "realm": {
    "name": "master"
  },
  "attributes": {
    "items": [
      {
        "name": {
          "match": "EXACT",
          "value": "meter_number",
          "predicateType": "string"
        },
        "value": {
           "predicateType": "boolean",
           "value": true
        }
      }
    ]
  }
}

Many of the predicates support negation if required (e.g. string attribute is not exactly equal to OK); also if your attribute value type is a JSON array or JSON object you can use the path field in the AttributePredicate to specify which index\key using an array with each item corresponding to a level, e.g.:

Given a JSON structure like:

{
  "obj1": {
    "obj1Key1": [
       {
          "obj2Key1": true
       }
    ]
  }
}

Then an attribute predicate for an attribute called meter_number to test obj2Key1 would be:

{
  "path": [
    "obj1",
    "obj1Key1",
    0,
    "obj2Key1"
  ],
  "name": {
    "match": "EXACT",
    "value": "meter_number",
    "predicateType": "string"
  },
  "value": {
    "predicateType": "boolean",
    "value": true
  }
}
2 Likes

Hi @admin, thanks a lot !!