Skip to content

JSON Queries

hlg edited this page May 4, 2025 · 14 revisions

The new query language is still in development, so expect this to change.

You can read the original motivations to write this language here

Intro

With the query language, you specify which entities or objects to include into the result. The various keywords of the query language, that is the field names of the JSON query, stand for diffent ways to restrict the result set of objects and to include additional objects.

Some characteristics of this language to keep in mind

  • The data model of the "query results" is the same data model as the one of the original "queried" from the database. In most cases it will be Ifc2x3tc1 or Ifc4. Same as the original data, it can be serialized in different ways though.
  • Consequently, there is no aggregation of values (such as COUNT, AVG, MAX, etc. in SQL), because there is no place to store those.
  • For the same reason, there is no selection or reordering of attributes (similar to projection in SQL). Attribute values can be undefined though.
  • A "query result" is always a subset of the original model.
  • "Query language" is probably not the best term here, a "filter language" might be better.
  • The queries are based on objects or entities. Geometry is not treated any other way. If you don't ask for geometry, you won't get it.

JSON

  • All queries must be valid JSON. This means that all keys must be quoted, all strings must be quoted.
  • When sending a query to BIMserver using the ServiceInterface.download method through the JSON API, ensure that your query is base64 encoded or quotation marks in the query are escaped, since you are nesting the query into the request JSON object as a string.
  • For further information regarding downloading the data via queries, please check Downloading models.

Restrict result to particular objects

There are four ways to restrict the result set:

  • Type (restriction to objects of a particular type)
  • GUID (restriction to objects with a particular globally unique identifier)
  • OID (restriction to objects with a particular object identifier)
  • Properties (restriction to objects with particular properties in a property set)

Base query

The empty query retrieves all objects in the scope (usually a particular revision) without any restrictions.

{
}

Each query can be further extended with additional field or properties to access the attributes and properties of the objects.

Type restriction

This query will get all IfcWall objects

{
  "type": "IfcWall"
}

When your model for example only contains IfcWallStandardCase objects, this query will not return any objects, although IfcWallStandardCase is a subtype of IfcWall. To include subtypes, you have to explicitly define this:

{
  "type": {
    "name": "IfcWall",
    "includeAllSubTypes": true
  }
}

You can also query multiple types, the next example would give you all IfcDoor and IfcWindow objects.

{
  "types": ["IfcDoor", "IfcWindow"]
}

GUID query

When you know the GUID of an object, you can query it directly.

{ "guid": "GUID1" }  

Likewise for multiple GUIDs.

{ "guids": ["GUID1", "GUID2"] }

The current implementation uses the GlobalId attribute of the IFC schema as GUID.

OID query

Same as for GUIDs, you can also query for objects with particular OIDs, the object IDs in the BIMserver database.

{ "oid": 1523 }

or

{ "oids": [1523, 2130, 898] }

Property restriction

Every IFC entity has a fixed set of attributes. For example the IfcWindow has the attributes "OverallWidth" and "OverallHeight" and many more. To use properties that are not defined in the schema, every object can be extended with more properties by adding them using IfcPropertySet and IfcProperty. For example IfcWall objects that are external can be queried via the property IsExternal in property set Pset_WallCommon:

{
  "type": {
     "name": "IfcWall",
     "includeAllSubTypes": true
  },
  "properties": {
    "Pset_WallCommon": {
      "IsExternal": true
    }
  }
}

Include further objects by following the object graph

Include query

You can "walk" the object object graph with include to follow a particular relation and include the related entity into the result as well. This is sometimes called "dereferencing". For every include you need to specify:

  • field: the name of the attribute to follow
  • type: the entity type where the attribute is defined (or inherited from a supertype)

The attribute must not be of a simple data type, but of an entity type establishing a relation towards another entity instance. You can then specify nested includes to follow the object graph across multiple edges.

For example:

{
  "type": "IfcWall",
  "include": {
    "type": "IfcWall",
    "field": "ContainedInStructure",
    "include": {
      "type": "IfcRelContainedInSpatialStructure",
      "field": "RelatingStructure"
    }
  }
}

For all the IfcWall elements in the dataset, the query dereferences the attributes as follows:

  • First, a type query is applied, to restrict the initial result set to IfcWall.
  • The first include retrieves the value of attribute ContainedInStructure for every object of type IfcWall. The attribute value is a reference to an instance of IfcRelContainedInSpatialStructure. The referenced objects are added to the result set.
  • The second include follows the RelatingStructure attribute from every IfcRelContainedInSpatialStructure object. The attribute value is a reference to an instance of IfcSpatialElement (or subtypes). Those are added to the result set as well.

The query can also follow multiple attributes of one object using includes:

{
  "type": "IfcBuildingStorey",
  "includes": [
    {
      "type": "IfcBuildingStorey",
      "field": "IsDecomposedBy",
      "include": {
        "type": "IfcRelAggregates",
         "field": "RelatedElements"
       }
    },
    {
      "type": "IfcBuildingStorey",
      "field": "ContainsElements",
      "include": {
        "type": "IfcRelContainedInSpatialStructure",
        "field": "RelatedElements"
      }
    }
  ]
}

Restricting included objects while following attributes

While following an attribute, with outputType or outputTypes you can restrict the types of objects to subtypes of the entity type the attribute is defined for. For example, the following query will only return all IfcWindow and IfcWallStandardCase objects that are contained in a spatial structure instead of any IfcProduct object:

{
"type": "IfcRelContainedInSpatialStructure",
"include":{
  "type": "IfcRelContainedInSpatialStructure",
  "field": "RelatedElements",
  "outputTypes": ["IfcWindow", "IfcWallStandardCase"]
  }
}

Serializing to IFC

In a lot of cases, the results of the query will be serialized as IFC. The previous examples would however not necessarily result in valid IFC files. For an IFC file to be valid, it has to solely contain objects that conform to the IFC schema, also some references (mandatoryattributes) should always be included. For example, in IFC2x3, the ... attribute is mandatory and every object of type IfcProduct must have a reference to an object of type IfcOwnerHistory.

Example of the body of an IFC file for the wall query.

#1= IFCWALLSTANDARDCASE('1hmUg1hfv4UPf0UtHFe7ta',$,'SW - 009',$,$,$,$,'6BC1EA81-AE9E-4479-9A-40-7B744FA07DE4');
#2= IFCWALLSTANDARDCASE('05UYVl82vAa8mFc3FMTYL7',$,'SW - 010',$,$,$,$,'057A27EF-202E-4A90-8C-0F-9833D6762547');
#3= IFCWALLSTANDARDCASE('37ZZt1nzL2nu6PjSr0Wa2a',$,'SW - 011',$,$,$,$,'C78E3DC1-C7D5-42C7-81-99-B5CD408240A4');
#4= IFCWALLSTANDARDCASE('1EzyXtTtv7RAinwkFVr6_I',$,'SW - 012',$,$,$,$,'4EF7C877-777E-476C-AB-31-EAE3DFD46F92');
#5= IFCWALLSTANDARDCASE('08u2EMNSnBL8Izk3LNHAwK',$,'SW - 013',$,$,$,$,'08E02396-5DCC-4B54-84-BD-B8355744AE94');

The above IFC file will not show anything in a 3D viewer because there are no geometric representations defined, for example: 2D or 3D coordinates of the object geometry and project units. Besides the actual geometry elements, the result would have to contain an IfcProject object with geometric context. Also, while the direct IFC attributes and their values are included in the result, property sets and properties are not, unless explicitly specified.

Predefined includes queries

As queries with all mandatory attributes and with geometry, become very complex and difficult to maintain, includes can be predefined and reused. For the IFC versions supported in BIMserver, there are some predefined includes available when executing the query. For every IFC schema, there is a respective standard library holding these predefined includes, for example ifc2x3-stdlib and ifc4-stdlib.

In order to include owner history, geometry (representation and context) and property sets, we need includes ContainedInStructure, OwnerHistory, Representation, ObjectPlacement, AllProperties. The include names must be prefixed with the name of the standard library they are defined in.

To make the IfcWall example work in IFC4, this would be the new query:

{
  "type": "IfcWall",
  "includeAllSubtypes": true,
  "includes": [
    "ifc4-stdlib:ContainedInStructure",
    "ifc4-stdlib:OwnerHistory",
    "ifc4-stdlib:Representation",
    "ifc4-stdlib:ObjectPlacement"
  ]
}

Each include is reponsible for a different portion of the object graph. Below are the functions of the predefined includes from the above query described.

ContainedInStructure

This makes sure all the spatial containment references "up" will be followed.
Example project structure:

IfcProject
  IfcSite
    IfcBuilding
      IfcBuildingStorey
        IfcSpace
          IfcWall

For every object, the spatial containment and aggregation tree will be "walked" all the way up. This automatically includes the IfcProject.

OwnerHistory

For every object, the OwnerHistory will be included.

Representation

For every object the Representation will be included. This can be a very large network/tree of objects. Representation is what gives object geometry in a 3D viewer.

ObjectPlacement

This makes sure that all objects will also include their placement, which puts the object's geometry in the right place.

AllProperties

For every object, all its referenced property set and properties are included.

Examples

Below are some examples of queries you can use. Additional examples can be found on BIMview.ws.

  • Query an object with specific GUID, including its properties:
{
  "guid": "1s2y3MJjT8AuHONdaM2zhl",
  "include": "ifc2x3tc1-stdlib:AllProperties"
}
  • Query a specific building storey, including all objects with their relations. The example below uses a Medical Dental Clinic project, which you can find here.
{
  "type": {
    "name": "IfcBuildingStorey"
  },
  "guid": "3eM8WbY_59RR5TDWs3wwJN",
  "includes": [
    {
      "type": "IfcBuildingStorey",
      "field": "IsDecomposedBy",
      "include": {
        "type": "IfcRelAggregates",
        "field": "RelatedObjects",
        "includes": [
          "ifc2x3tc1-stdlib:Representation",
          "ifc2x3tc1-stdlib:ObjectPlacement",
          "ifc2x3tc1-stdlib:AllProperties"
        ]
      }
    },
    {
      "type": "IfcBuildingStorey",
      "field": "ContainsElements",
      "include": {
        "type": "IfcRelContainedInSpatialStructure",
        "field": "RelatedElements",
        "includes": [
          "ifc2x3tc1-stdlib:Representation",
          "ifc2x3tc1-stdlib:ObjectPlacement",
          "ifc2x3tc1-stdlib:AllProperties",
          {
            "type": {
              "name": "IfcBuildingElement",
              "includeAllSubTypes": true
            },
            "field": "HasOpenings",
            "include":{
              "type": "IfcRelVoidsElement",
              "field": "RelatedOpeningElement",
              "includes": [
                {
                  "type": "IfcOpeningElement",
                  "field": "HasFillings",
                  "include": {
                    "type": "IfcRelFillsElement",
                    "field": "RelatedBuildingElement",
                    "includes":[
                      "ifc2x3tc1-stdlib:Representation",
                      "ifc2x3tc1-stdlib:ObjectPlacement",
                      "ifc2x3tc1-stdlib:AllProperties"
                    ]
                  }
                },
                "ifc2x3tc1-stdlib:Representation",
                "ifc2x3tc1-stdlib:ObjectPlacement"
              ]
            }
          },
          {
            "type": "IfcBuildingElement",
            "field": "IsDecomposedBy",
            "include":{
              "type": "IfcRelAggregates",
              "field": "RelatedObjects",
              "includes":[
                "ifc2x3tc1-stdlib:Representation",
                "ifc2x3tc1-stdlib:ObjectPlacement",
                "ifc2x3tc1-stdlib:AllProperties"
              ]
            }
          }
        ]
      }
    },
    "ifc2x3tc1-stdlib:Decomposes"
  ]
}
Clone this wiki locally