How to query more than one element in a Revit model

Hello everyone,

I am trying to query a Revit model for more than one element, but i cannot figure out how to. I can figure out how to query single element like so:

query {
  stream(id:"my-stream-id") {
    object(id:"my-element-id") {
      id
      speckleType
    }
  }
}

But in this case, i only query the specific element with the id my-element-id which i found from the speckle viewer.

How can i query more than one element from a Revit model? I am going to use this knowledge to e.g. query all pipes and filter them by a specific pipe type or attached system type, and to be able to do this query is kindain order to achieve this.

Hello :wave:

I’m new here, so this may not be the best/correct way to go about this…

We found that if you get a referencedObject out of a commit, then query that object and all it’s children to a sufficient depth/count, then you end up with all objects:

First query:

  query getStream ($id: String!, $branchName: String!) {
        stream (id: $id) {
          id
          branch(name: $branchName) {
            commits {
              items {
                id
                branchName
                referencedObject
                totalChildrenCount
              }
            }
          }
        }
      }

Second query:

query getStream ($id: String!, $objectId: String!, $childCount: Int!) {
        stream (id: $id) {
          id
          name
          object(id: $objectId) {
            id
            children(limit: $childCount, depth: 100) {
              objects {
                id
                data
              }
            }
          }
        }
      }

The correct way is probably to switch over to the REST API :person_shrugging:

Good luck

2 Likes

Amazing, that worked! It would be nice to have some good documentation on how the datastructure around Revit models converted to Speckle models looks like. I have no idea exactly what referenceObject exactly is, does it contain >everything< in the model? Or what does it contain?

:+1: to wanting to know more about the Revit connector works, etc… Maybe I haven’t stumbled upon the doc yet :person_shrugging:

We have found that the speckle data does not include everything but only the objects which are in the view you are exporting. For instance, if you are using Design Options, only the options which are turned on will be included in the speckle data. (Though, this is something we are actively looking into whether there is a better way to get all the option data in a single commit)

Are you sure? Because on the Revit Connector, i can select everything, at it seems like everything is exported from the model to Speckle. Otherwise the Docs on the Revit Connector seems well explained, but it does not talk about the underlaying data structure, which i think could be very relevant for a developer. Here the docs mention something about Design Options.

Thanks for the document links. That is helpful.

There is this thread about the handling of send everything and design options. Perhaps it is out dated information, but seems to align with our findings. (though I want to to try everything again to confirm :laughing: )

1 Like

You are right @Christopher_Fox , we are using the active design option and send everything as the other way would result in weird results in 3d viewer.

You are new but solved your first issue already!

1 Like

It’s an interesting debate, and we can better document some of this.

@ONO, you are right; there are many different ways to slice and dice the Revit data when electing what to send.

@Christopher_Fox Sometimes, the best strategy for Speckle operations is to make the most of the ability not to send everything in one big go. Preparing to make multiple objectively focussed queries can save some time on receiving.

A feature of the GraphQL API is the ability to alias concatenated queries to additional data points

query concatenatedQuery ($id: String!, $objectId: String!, $childCount: Int!) {
        A: stream (id: $id) {
          object(id: $objectId) {
            children(limit: $childCount, depth: 100) {
              objects {
                id
              }
            }
          }
        }
     B: stream (id: $id) {
          object(id: $objectId) {
            children(limit: $childCount, depth: 100) {
              objects {
                id
              }
            }
          }
        }
      }

To return to your original question @ONO you can do a lot with the GraphQL API to be focussed and also expansive. I went into a few of the ways to manipulate your queries in an open office session last year: https://youtu.be/J0SbxMFFbfc?si=XK5yonTcXMydhSmw

Adding a query to the children object allows you to specify a singular speckle_type
Adding a select field to the children object allows you to specify the list of parameters you are interested in

Therefore, combining my answer to @Christopher_Fox with your original intended use case retrieves MEP Connectors for two separate versions (and parameterises these for both queries":

Query

query groupCommits($id: String!, $myQuery: [JSONObject!], $select: [String], $depth: Int!, $commitReferencedObjectId1: String!, $commitReferencedObjectId2: String!, $childCount: Int!) {
  commit1: stream(id: $id) {
    object(id: $commitReferencedObjectId1) {
      id
      children(select: $select, query: $myQuery, limit: $childCount, depth: $depth) {
        objects {
          id
          data
        }
      }
    }
  }
  commit2: stream(id: $id) {
    object(id: $commitReferencedObjectId2) {
      id
      children(select: $select, query: $myQuery, limit: $childCount, depth: $depth) {
        objects {
          id
          data
        }
      }
    }
  }
}

Parameter variables:

{
  "id": "da888___",
  "commitReferencedObjectId1": "1590a069d983fdf3dc6____",
  "commitReferencedObjectId2": "dc62f5e7903d76ae159____",
  "childCount": 3,
  "depth": 10,
  "select": [
    "systemName",
    "speckle_type",
    "applicationId"
  ],
  "myQuery": [
    {
      "field": "speckle_type",
      "value": "Objects.BuiltElements.Revit.RevitMEPConnector",
      "operator": "="
    }
  ]
}

Indicative output of this would be:

{
  "data": {
    "commit1": {
      "object": {
        "id": "1590a069d983fdf3dc62f5e7903d76ae",
        "children": {
          "objects": [
            {
              "id": "005cec1c1b3cd09976f326e0cb32468a",
              "data": {
                "systemName": "P-ARPIS VENT 21",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-000451eb.1",
                "id": "005cec1c1b3cd09976f326e0cb32468a"
              }
            },
            {
              "id": "013f03caee4966561103a7d725b3fa86",
              "data": {
                "systemName": "P-ARPIS SAN 7",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-0004514d.3",
                "id": "013f03caee4966561103a7d725b3fa86"
              }
            },
            {
              "id": "0168671cb2ab7d84336e4997b292934e",
              "data": {
                "systemName": "P-ARPIS VENT 7",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-000451a1.2",
                "id": "0168671cb2ab7d84336e4997b292934e"
              }
            }
          ]
        }
      }
    },
    "commit2": {
      "object": {
        "id": "1590a069d983fdf3dc62f5e7903d76ae",
        "children": {
          "objects": [
            {
              "id": "005cec1c1b3cd09976f326e0cb32468a",
              "data": {
                "systemName": "P-ARPIS VENT 21",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-000451eb.1",
                "id": "005cec1c1b3cd09976f326e0cb32468a"
              }
            },
            {
              "id": "013f03caee4966561103a7d725b3fa86",
              "data": {
                "systemName": "P-ARPIS SAN 7",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-0004514d.3",
                "id": "013f03caee4966561103a7d725b3fa86"
              }
            },
            {
              "id": "0168671cb2ab7d84336e4997b292934e",
              "data": {
                "systemName": "P-ARPIS VENT 7",
                "speckle_type": "Objects.BuiltElements.Revit.RevitMEPConnector",
                "applicationId": "9819452a-0461-4d94-bca6-5b6a1b881d7b-000451a1.2",
                "id": "0168671cb2ab7d84336e4997b292934e"
              }
            }
          ]
        }
      }
    }
  }
}
2 Likes

Is it also possible to select sub-properties within the select variable? After some testing that seems possible using something like “property.subproperty”, but again the “-” are making some trouble in case of accessing shared parameters:

grafik

Adding quotes and escaping them …

grafik

… somehow helps, but the result doesn’t look like expected:

grafik

plus: it makes it quite weird in the code, because there I have to escape the escape character so that the escape character can escape the " within the API …

Is there a better way?

Sadly there is no other way - retrieve as little as possible and then filter client side. No single shot solutions exist.

1 Like

I also noticed, that the depth parameter seems to behave weird, or am I not getting something right?

In my case, a depth of e.g. 9 got all the children. A depth of 10 or above would only return the first hierarchy level and much less objects - like depth would be 2 or so.


Hello @samberger, i wholeheartedly recommend you do not use the max depth parameter. It’s flagged in my head as “superfluous”. It’s reliant on SDKs and scripts doing the right thing, and that’s not the case; it’s not enforced on the server level.

What are you using it for, and is it critical for that? If you’re just exploring, do ignore it!

1 Like

Hey @dimitrie!

Thanks! Good to know! :slight_smile:

Basically I just want to get all the built elements / objects of a model version, without going through all the collections and sub-collections and sub-sub-collections … (especially since the DUI3 Revit connector seems to increasingly use those).

In that case, I’m not caring about object hierarchy or collections, I just wanted to get all the materialQuantities from all the elements (who have that property).
Yes, it’s for a LCA. :sweat_smile:

But I guess I just left the parameter completely, and I will always get all the children? Didn’t realize it’s a max-depth parameter…

I use it ONLY when i want to be very lightweight top level of what i want to filter and return - it has a use