Skip to content

Query System

Ardeshir Talaei edited this page Nov 8, 2022 · 4 revisions

Speckle Query is a part of the Grasshopper plugin that has been developed for this project. It enables the user to generate and run GraphQL queries on the streams and branches, from inside the Grasshopper. The queries consist of the target stream (or a branch's or commit's URL), a series of key/value parameters to be searched for, and a list of parameters to be returned as a result.

Architecture

The query system enables searching for objects based on a set of key/value pairs, and returns the ID and URL of the objects that match the query. If specified, it can also return the specified properties of the objects that match the query. The system also allows for the nested queries, where the system can run a second query on the children of the objects that meet the criteria of the first query.
The query system uses a layered architecture to capture the nesting capabilities of the queries. Each query is defined as a layer with its own key/value pairs and return list. These query layers can be stacked on each other and each query runs on the children of the objects that are returned from its previous layer.

Query Layers

A query layer is a single query that can be ran on a Speckle Object. each commit is also a Speckle Object that holds all the objects of that commit as its children. A Query Layer has a series of criteria (key/value pairs in form of a Query Parameter), a list of Fields that define the parameters to be returned from each object that matches the criteria. Also, a depth value on each layer defines how deep to into the children tree a child object should be searched for.

QueryLayerComponent

Fields

Defines a list of all the parameters (fields) to has to be returned from the objects that match the query. The ID of the object is a mandatory field that is always returned, even if not enlisted.

Query Parameters

Each query parameter consists of a key, a value, and an operator that defines the logical operation for testing (==, !=, <, >, <=, >=). The query only returns that has the key, and its value matches the defined value considering the logical operator.
Each query layer has one or more Query Parameters. These parameters are combined using AND, meaning the query will only return results that match all the query parameters.

Query Results

The Query component in grasshopper returns the Stream ID of the queried stream, Object IDs of all the objects in the stream that met the criteria, and URL of all those objects. The component also return the Fields that has been requested from the last query layer.

In order to access the Fields that have been requested from other layers, the Query Result component can be used. This component takes the out output from the Query component and the layer number to extract the Fields from as the input. The component then returns the Objecct ID of all the objects in that layer that met the criteria, the Fields that have been requested from those objects, and the Fields that were requested from the next layer objects. This last output is especially usefull for matching the children with their parent object.

Note
Each query layer returns all the objects in that layer that meet the criteria, despite if they have any children that match the next query layer.

In C#, a query will return a JSON fromatted string with the same structure as the query that was executed. The requested fields of each layer are tagged with result_layer* key where the * represents the layer's 1-based index number. The query system also has a utility function that helps parsing the JSON results and extract the results of a specific layer.

Examples

Simple Query Example (Grasshopper)

This is an example query in Grasshopper that searches for all the objects with a material field that equals ecoplex and a thickness field that equals 12.

ExampleSimpleQuery

Nested Query Example (Grasshopper)

This is an example query in Grasshopper that searches for all the objects with a specific sheet_name field and then looks for all the children of that object that their speckle_type field equals BCFKit.Types.BCFPart.

ExampleNestedQuery

Finding the Parent of an Object

Nested Query Ecample (C#)

Following code is a sample query in C# that looks for all the sheet objects in a stream and returns the material of them, and also looks for all the part objects in each sheet and returns the part_name, and material of them.

var acc = AccountManager.GetDefaultAccount();
var agent = new QueryAgent(acc)
      {
        Stream = new StreamWrapper(Stream_URL_To_Query)
      };
      agent.AddLayer(10);
      agent.layers[0].AddQuery("sheet_name", "", "!=");
      agent.layers[0].fields = new List<string> { "material", "speckle_type" };

      agent.AddLayer(10);
      agent.layers[1].AddQuery("part_name", "", "!=");
      agent.layers[1].fields = new List<string> { "part_name", "material", "speckle_type" };

      agent.GenerateQueryVariables().Wait();
      agent.GenerateQueryString();
      var queryResult = agent.RunQuery().Result;

      foreach (var kvp in queryResult)
      {
        Console.WriteLine("Testing . . .");
        Console.WriteLine(
            string.Join(",, ",
                ((JObject)kvp.Value).Children().Select(r => r.First.ToString()).ToList())
        );
      }

      var l0 = agent.GetLayer(0);
      foreach (var kir in l0.Values.First().Item2)
      {
        Console.WriteLine((string)kir.result_data.part_name);
      }

      var l1 = agent.GetLayer(1);
      foreach (var kvp in queryResult)
      {
        Console.WriteLine(kvp.Key);
        Console.WriteLine(kvp.Value.ToString());
        Console.WriteLine();
      }