How to create a relationship to multiple targets in digital twins?

Gorthi Sai Sri Sindhuja 60 Reputation points
2023-08-09T09:58:22.07+00:00

We created twins in digital twins using python, and tried creating relationships.

We want to establish a relationship with same relationship name and from the same source that should be connected to different targets. But We constantly get the following error:

RestError: Twin relationship does not align with the model. Please ensure that the relationship is in alignment with the model.

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.
231 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Sander van de Velde | MVP 33,136 Reputation points MVP
    2023-08-09T11:22:15.95+00:00

    Hello @Gorthi Sai Sri Sindhuja ,

    can you check the model you want to connect with using a relationship has the correct model ID? Is it having the right version of the model?

    User's image

    As seen here, all floors must have a model of "dtmi:com:adt:dtsample:home:rel_has_floors;1".


    If the response helped, do "Accept Answer". If it doesn't work, please let us know the progress. All community members with similar issues will benefit by doing so. Your contribution is highly appreciated.


  2. LeelaRajeshSayana-MSFT 16,046 Reputation points
    2023-08-09T16:16:26.7866667+00:00

    Hi @Gorthi Sai Sri Sindhuja Greetings! It looks like you are trying to set a relationship through the target property. In addition to the details shared by Sander, I would like to point that the target property in the model definition specifies which types of twins the relationship can reach. For example, you might include a target to specify that a Building model can only have a has relationship with twins that are of model Floor. This cannot be used to set/bind targets relationships with the actual digital twins. Please refer the section Targeted and non-targeted relationships in Azure Digital Twins documentation for more details on this.

    To establish a relationship, you can use the upsert_relationship method of the Python SDK and pass the source and target twin details to create this relationship.

    Here is a sample code to achieve this.

    import asyncio
    from azure.identity import DefaultAzureCredential
    from azure.digitaltwins.core import DigitalTwinsClient
    import json
    
    async def main():
        adt_instance_url = "https://<ADTHostName>"
        credential = DefaultAzureCredential()
        client = DigitalTwinsClient(adt_instance_url, credential)
        print("Service client created – ready to go")
    
        with open("Home.json") as f:
            dtdl = json.load(f)
    
        print()
    
        homeModel = {
            "@id": "dtmi:com:contoso:home;1",
            "@type": "Interface",
            "@context": "dtmi:dtdl:context;2",
            "displayName": "Home",
            "contents": [
                {
                    "@type": "Property",
                    "name": "id",
                    "schema": "string"     
                },    
                {
                    "@type": "Relationship",
                    "name": "rel_has_floors",
                    "target": "dtmi:com:contoso:floor;1"
                }
            ]
        }
    
        floorModel = {
            "@id": "dtmi:com:contoso:floor;1",
            "@type": "Interface",
            "@context": "dtmi:dtdl:context;2",
            "displayName": "Floor",
            "contents": [
                {
                    "@type": "Property",
                    "name": "level",
                    "schema": "string"
                }
            ]
        }
        
        # Upload the models to ADT instance
        client.create_models([homeModel, floorModel])
    
        #Creating a twin for home
        twin_data = {
            "$metadata": {
                "$model": "dtmi:com:contoso:home;1"
            },
            "id": f"Hello World!"
        }    
    
        #Create the digital twin using the upsert_digital_twin method
        digital_twin_id = "Home1"
        client.upsert_digital_twin(digital_twin_id, twin_data)
    
        #Creating Twins for floors
        twin_data = {
            "$metadata": {
                "$model": "dtmi:com:contoso:floor;1"
            },
            "level": f"Test level"
        }
    
        digital_twin_id = "Floor1"  
        client.upsert_digital_twin(digital_twin_id, twin_data)  
        digital_twin_id = "Floor2"  
        client.upsert_digital_twin(digital_twin_id, twin_data)  
        digital_twin_id = "Floor3"  
        client.upsert_digital_twin(digital_twin_id, twin_data)  
    
        create_relationship(client, "Home1", "Floor1")
        create_relationship(client, "Home1", "Floor2")
        create_relationship(client, "Home1", "Floor3")
    
    
    
    
    def create_relationship(client, src_id, target_id):
        relationship = {
            "$targetId": target_id,
            "$model": "dtmi:com:contoso:home;1",
            "$relationshipName": "rel_has_floors"
        }
        rel_id = f"{src_id}-rel_has_floors->{target_id}"
        try:
            client.upsert_relationship(src_id, rel_id, relationship)
            print("Created relationship successfully")
        except Exception as e:
            print(f"Create relationship error: {e}")
    
    
    if __name__ == "__main__":
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
    
    

    Please note that the src_id is the source /parent digital twin ID and target_id is the ID of the twin to which the relationship needs to be established.

    Once the code executes, you can see that the twins get created with the correct relationships on the ADT instance. Please refer the below image.

    enter image description here

    Hope this helps!

    We noticed your feedback that the above answer was not helpful. Thank you for taking time to share your feedback. Kindly let us know what we could have done better to improve the answer and make your engagement experience good. We are here to help you and strive to make your experience better and greatly value your feedback. Looking forward to your reply. Much appreciate your feedback! If you wish, you may consider re-surveying/rating for the engagement you received on the thread.

    If the response helps, please mark the answer as Accepted Answer and Yes to help identify solution to other community members facing a similar issue.


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.