Query Levels via GraphQL

hi everyone,
I am trying to query all the levels on a commit coming from Revit via graphql, wonder if I could get some help? I can see the { level } objects in the speckle viewer, but this graphql query always returns me 0 objects. I also tried with “category” = “Levels” :

query (
  $myQuery: [JSONObject!], 
  $streamId: String!,
  $objectId: String!) 
{
  stream(id: $streamId) {
    object(id: $objectId) {
      children(query: $myQuery, limit: 1000, depth: 100) {
        totalCount
        objects {
          data 
					
        }
      }
    }
  }
}

variables:

{
  "streamId": "...",
  "objectId": "...",
  "myQuery": [
        {
      "field": "speckle_type",
      "value": "Objects.BuiltElements.Level:Objects.BuiltElements.Revit.RevitLevel",
      "operator": "="
        }

  ]
}

thanks for any help :slight_smile:

2 Likes

There are two possible answers here.

Where a commit has been made of Project Information and Including Levels, you can retrieve the levels of the project exactly in as your example code:

The web view will show them up as distinct elements in an array:

Getting levels used in a commit is a little more complicated… If you want to retrieve the Levels from a commit of objects, no query object can isolate those elements. Because the query filter works on a list of child objects, and the Levels are referenced as the properties of an object, the previous example doesn’t work … as you have discovered.

However, what can be done is a query on the commit to only return objects that have a level as a property .

 "myQuery":[ 
  	{
      "field": "level.speckle_type",
      "value": "Objects.BuiltElements.Level:Objects.BuiltElements.Revit.RevitLevel",
      "operator": "="
    }
  ]

This certainly filters out any object in the commit that doesn’t have a level property which is in turn not Objects.BuiltElements.Level:Objects.BuiltElements.Revit.RevitLevel. However in truth, so would

 "myQuery":[ 
  	{
      "field": "level.speckle_type",
      "value": "Susan's awesome level object",
      "operator": "!="
    }
  ]

This validates the level.speckle_type field being present and will omit objects without a level property.

While that will return a lot of redundancy, your own code can then filter the data prop, extract what information about the Level you wish and dedupe.

e.g (python),

# Load the JSON data into a Python object
data = json.loads(json_data) # Where json_data is the graphql result

# Extract the levels from the data
levels = [obj['data']['level'] for obj in data['objects']]

# De-duplicate the levels
unique_levels = [dict(t) for t in set(tuple(level.items()) for level in levels)]

or js

let data = /* Result from query */

let levels = data.objects.map(obj => obj.data.level);

// De-duplicate the levels
let uniqueLevels = Array.from(new Set(levels.map(JSON.stringify))).map(JSON.parse);

A c# example would probably be the methodology of your choice, Linq?, but that should be enough.

3 Likes

hi @jonathon,

thank you for the really comprehensive response!

Both are really good solutions, and since as we have a lot of control on what we are pushing we will start to send the levels as is more simple. However it is also great to have a fallback strategy in case those are missing!

1 Like