How to return a graph with nested twins?

Klaus Nørregaard 11 Reputation points
2023-03-14T14:42:40.2466667+00:00

Hi

Is there a way to return a graph structure as a nested structure?

User's image

When I query this structure I have to use the relationship nodes an create a nested data structure of my own. Is it possible to use eg. the API to query the structure so that it returns the objects as nested? So the RuleC and RuleCC is nested objects in RuleA etc.

Azure Digital Twins
Azure Digital Twins
An Azure platform that is used to create digital representations of real-world things, places, business processes, and people.
236 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. LeelaRajeshSayana-MSFT 17,766 Reputation points Moderator
    2023-03-14T17:44:31.2966667+00:00

    @Klaus Nørregaard Thanks for using Microsoft Q&A forum and posting your query. Could you please provide more details on what your nested data structure would look like? Are you planning to create a list of relationships for each node and have a record of its child nodes associated with it? By that, I mean should the output based on your twin graph should look as follows-

    1. P1 -> RuleManife...
    2. RuleManife.. -> RuleA
    3. RuleA -> RuleC, RuleCC

    If so, we can leverage the Query API of digital twin graph to fetch these values and get the desired result. Here is the code I have used in C# to perform the Digital Twin search and pull the results.

    using System;
    using Azure.DigitalTwins.Core;
    using Azure.Identity;
    using System.Threading.Tasks;
    using System.IO;
    using System.Collections.Generic;
    using Azure;
    using System.Text.Json;
    
    namespace MyApp // Note: actual namespace depends on the project name.
    {
        internal class Program
        {
            static async Task Main(string[] args)
            {
                Console.WriteLine("Hello World!");
    
                string adtInstanceUrl = "https://<DigitalTwinIsntanceID>.api.eus.digitaltwins.azure.net";
    
                var credential = new DefaultAzureCredential();
                var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
                Console.WriteLine($"Service client created – ready to go");
    
                string twinname;
                string twinQuery = "SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:example:GraphModel;2')";
                // Run a query for all twins            
                string queryChildren;            
                Dictionary<string, List<string>> childrelationship = new Dictionary<string, List<string>>();
                AsyncPageable<BasicDigitalTwin> twinResult = client.QueryAsync<BasicDigitalTwin>(twinQuery);
    
                await foreach (BasicDigitalTwin twin in twinResult)
                {
                    Console.WriteLine(JsonSerializer.Serialize(twin.Id));
                    twinname = twin.Id;                
                    queryChildren = "SELECT DT FROM DIGITALTWINS twin JOIN DT RELATED twin.contains WHERE twin.$dtId = '" + twinname + "'";                
                    AsyncPageable<JsonElement> queryChildrenResult = client.QueryAsync<JsonElement>(queryChildren);
                    List<string> childnodes = new List<string>();
                    await foreach (JsonElement twinresult in queryChildrenResult)
                    {                    
                        try
                        {
                            childnodes.Add(twinresult.GetProperty("DT").GetProperty("$dtId").ToString());
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                    }
                    childrelationship.Add(twinname, childnodes);
                    Console.WriteLine("---------------");
                }
                Console.WriteLine();
                foreach (KeyValuePair<string, List<string>> kvp in childrelationship)
                {
                    Console.WriteLine("Key = {0}, Value = {1}",
                        kvp.Key, String.Join(",", kvp.Value));
                }
            }
        }
    }
    

    I have performed a search operation on the following Digital Twin graph to fetch each child node.

    bkw8b.png (1178×665)

    Here is the output I captured into a collection that records a list of child nodes for a given node.

    User's image

    Kindly provide more details if my understanding of your use case is incorrect and we would be glad to help you.


     If the response helped, do Mark the answer as useful. All community members with similar issues will benefit by doing so. If it doesn't work, please let us know the progress and we would be glad to assist you. Your contribution is highly appreciated.  

    1 person found this answer helpful.
    0 comments No comments

  2. QuantumCache 20,366 Reputation points Moderator
    2023-03-14T17:47:29.83+00:00

    Hello @@Klaus Nørregaard, Thanks for posting this helpful query over here!

    Adding few more points to Leela's Answer!

    Yes, it is possible to query Azure Digital Twins to return a graph structure as a nested data structure using the API. One approach to achieving this is by using the $expand query option in the API query to include related entities in the response payload.

    For example, suppose you have a Digital Twin graph that contains entities of type "Rule" that are related in a hierarchy. You can use the following API query to retrieve the rules with their related child rules as nested objects:

    GET /digitaltwins/{digitalTwinId}/relationships/{relationshipName}?$expand=children&$filter=$dtId eq '{ruleId}'

    In the above query, {digitalTwinId} is the ID of the Digital Twin instance containing the rules, {relationshipName} is the name of the relationship that links the rules, and {ruleId} is the ID of the parent rule you want to retrieve. The $expand=children query option specifies that you want to include related child entities in the response payload.

    When you execute this query, the response payload will include the parent rule and its related child rules as nested objects, as shown below:

    {
        "@context": "https://example.com/ctx.json",
        "id": "ruleA",
        "name": "Rule A",
        "children": [
            {
                "@context": "https://example.com/ctx.json",
                "id": "ruleB",
                "name": "Rule B",
                "children": [
                    {
                        "@context": "https://example.com/ctx.json",
                        "id": "ruleC",
                        "name": "Rule C"
                    }
                ]
            },
            {
                "@context": "https://example.com/ctx.json",
                "id": "ruleCC",
                "name": "Rule CC"
            }
        ]
    }
    
    

    In the above response payload, RuleA contains two child rules (RuleB and RuleCC), and RuleB contains one child rule (RuleC).

    By using the $expand query option in the API query, you can retrieve related entities as nested objects in the response payload, which can simplify data processing and eliminate the need to manually create a nested data structure.


    If this answers your query, do click Accept Answer  as helpful. And, if you have any further query do let us know by commenting in the below section. Happy to help!


  3. Klaus Nørregaard 11 Reputation points
    2023-03-15T10:05:10.2633333+00:00

    Hi Thanks for your replies...

    I am doing this query: https://{{digitaltwins-hostname}}/digitaltwins/RuleManifestA/relationships/5cc12434-2223-47ed-ba1a-2a4f3ed2db8e?$expand=children&api-version=2020-10-31

    It only returns a partial part of the data.

    User's image

    And the data is like this.

    {
        "$relationshipId": "5cc12434-2223-47ed-ba1a-2a4f3ed2db8e",
        "$etag": "W/\"5f3d61fe-2bf1-465f-8cdc-556ce25a1968\"",
        "$sourceId": "RuleManifestA",
        "$relationshipName": "rel_contains_rules",
        "$targetId": "RuleA"
    }
    

    How can I return a data respresentation that has the following structure?

    {
        "$relationshipId": "5cc12434-2223-47ed-ba1a-2a4f3ed2db8e",
        "$etag": "W/\"5f3d61fe-2bf1-465f-8cdc-556ce25a1968\"",
        "$sourceId": "RuleManifestA",
        "$relationshipName": "rel_contains_rules",
        "$targetId": "RuleA"
        "Rules": [{
            ....
            $soucerId : "RuleA",
            ....
            "Rules" : [
                {
                     .....
                     $sourceId : "RuleCC"
                     .....
                },
                {
                     .....
                     $sourceId : "RuleC"
                     ....
                },
    
      
            ]
        }]
    },
        ....
    }
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.