Cannot make Grahviz's edge go straight and render correctly after adding a new node

Viewed 127

I am pretty enjoy about the power of Graphviz and are trying to convert a wonderful .NET Core learning roadmap from .Net Core Developer Roadmap to Graphviz Dot for easier to update later.

The layout is okay until I added a new caching node and I cannot control Graphviz to render correctly.

Here is the code.

digraph learning_roadmap {
    node[shape=none, width=0, height=0, label=""];
    edge[dir=none];

    subgraph main_group {
        main0 [label = "ASP.NET Core developer"]
        prerequisites [label = "Learn the Prerequisites"]

        main1 -> main2 
        main2 -> main3 
        main3 -> main4 [minlen=4] 
        main4 -> main5 [minlen=4] 
        main5 -> main6 [minlen=4] 

        main6 -> main7 [minlen=4]
        main7 -> main8 [minlen=5]
        main8 -> main9 [minlen=1]
        main9 -> main10 [minlen=5]

        {rank=same; main2 -> prerequisites}
        {rank=same; cs -> main3}
        {rank=same; main4 -> ef}

        {rank=same; asp -> main5}
        {rank=same; main6 -> sql}
        {rank=same; general_skill -> main7}
        {rank=same; main8-> di}
        {rank=same; db -> main9}
        {rank=same; main10 -> caching}
    }

    subgraph cs_group {
        cs [label = "C#"]
        cs_basic [label = "Learn the basics of C#"]
        linq [label = "Learn LINQ"]

        cs1 -> cs2 
        {rank=same; cs1 ->  cs}
        {rank=same; cs_basic ->  cs1}
        {rank=same; linq -> cs2}
    }

    subgraph ef_group {
        ef [label = "Entity"]

        ef_basic [label = "Learn the basics of Entity Framework"]
        ef_code_first [label = "Code First + Migrations"]
        ef_tracking [label = "Change Tracker API"]
        ef_loading [label = "Lazy Loading. Eager Loading, Explicit Loading"]

        ef1 -> ef2 -> ef3 -> ef4 
        {rank=same; ef -> ef1}
        {rank=same; ef1 ->  ef_basic}
        {rank=same; ef2 ->  ef_code_first}
        {rank=same; ef3 -> ef_tracking}
        {rank=same; ef4 -> ef_loading}
    }

    subgraph asp_group {
        asp [label="ASP.NET Core Basics"]

        mvc [label="MVC"]
        rest [label="REST "]
        razor_page [label="Razor Pages "]
        razor_component [label="Razor Components "]
        middlewares [label="Middlewares "]
        filter [label="Filters & Attributes "]
        setting [label="Application Settings & Configurations"]

        asp1 -> asp2 -> asp3 -> asp4 -> asp5 -> asp6 -> asp7

        {rank=same; asp1 -> asp}
        {rank=same; mvc -> asp1}
        {rank=same; rest -> asp2}
        {rank=same; razor_page ->  asp3}
        {rank=same; razor_component -> asp4}
        {rank=same; middlewares -> asp5}
        {rank=same; filter -> asp6}
        {rank=same; setting -> asp7}
    }

    subgraph sql_group {
        sql [label="SQL Fundamentals"]
        sql_basic [label="Fundamentals about database design and SQL Syntax"]

        {rank=same; sql -> sql_basic}
    }

    subgraph general_skill_group {
        general_skill [label="General Development Skills"]
        git [label="GIT - Version Control (GitHub, BitBucket, GitLab)"]
        http [label="HTTP/HTTPS protocol Learn to search for solutions"]
        search [label="Learn to search for solutions"]
        dotnet_cli [label="Learn Dotnet CLI"]
        data_structure [label="Data Structures and Algorithms"]

        general1 -> general2 -> general3 -> general4 -> general5

        {rank=same; general1 -> general_skill}
        {rank=same; git -> general1}
        {rank=same; http -> general2}
        {rank=same; search -> general3}
        {rank=same; dotnet_cli -> general4}
        {rank=same; data_structure -> general5}
    }  

    subgraph di_group{
        di [label="Dependency Injection"]
        di_containers [label="DI Containers"]
        scrutor [label="Scrutor"]
        life_cycles [label="Life Cycles"]

        di1 -> di2 -> di3 
        {rank=same; di -> di2}
        {rank=same; di1 -> di_containers}
        {rank=same; di2 -> scrutor}
        {rank=same; di3 -> life_cycles}

        # DI Frameworks
        ms_di [label="Microsoft.Extensions.DependencyInjection"]
        autofac [label="Autofac"]
        ninject [label="Ninject"]
        castle_winsor [label="Castle Winsor"]
        unity [label="Unity"]

        di_container1 -> di_container2 -> di_container3 ->di_container4 -> di_container5

        {rank=same; di_containers -> di_container1 [minlen=7] }
        {rank=same; di_container1 -> ms_di}
        {rank=same; di_container2 -> autofac}
        {rank=same; di_container3 -> ninject}
        {rank=same; di_container4 -> castle_winsor}
        {rank=same; di_container5 -> unity}

        # Scope
        trasient [label="Trasient"]
        scoped [label="Scoped"]
        singleton [label="Singleton"]

        life_cycle1 -> life_cycle2 -> life_cycle3

        {rank=same; life_cycles -> life_cycle1}
        {rank=same; life_cycle1 -> trasient}
        {rank=same; life_cycle2 -> scoped}
        {rank=same; life_cycle3 -> singleton}
    }

    subgraph db_group {
        db [label="Databases"]
        relational_db [label="Relational"]
        cloud_db [label="Cloud Databases"]
        search_engine [label="Search Engines"]
        no_sql [label="NoSQL"]

        db1 -> db2 [minlen=6]
        db2 -> db3 [minlen=5]
        db3 ->  db4 [minlen=3]

        {rank=same; db1 -> db}
        {rank=same; relational_db -> db1}
        {rank=same; cloud_db -> db2}
        {rank=same; search_engine -> db3}
        {rank=same; no_sql -> db4}

        # Relational databases
        sql_server [label="SQL Server"]
        postgresql [label="PostgreSQL"]
        mysql [label="MySQL"]
        sqlite [label="SQLite"]

        relational_db1 -> relational_db2 -> relational_db3 -> relational_db4

        {rank=same; relational_db2 -> relational_db [minlen=5] }
        {rank=same; sql_server -> relational_db1}
        {rank=same; postgresql -> relational_db2}
        {rank=same; mysql -> relational_db3}
        {rank=same; sqlite -> relational_db4}

        # Cloud Databases
        azure_sql_database [label="Azure SQL Database"]
        cosmos_db [label="Azure CosmosDB"]
        rds [label="Amazon RDS"]
        aurora [label="Amazon Aurora"]
        dynamo_db [label="Amazon DynamoDB"]

        cloud_db1 -> cloud_db2 -> cloud_db3 -> cloud_db4 -> cloud_db5

        {rank=same; cloud_db1 -> cloud_db}
        {rank=same; azure_sql_database -> cloud_db1}
        {rank=same; cosmos_db -> cloud_db2}
        {rank=same; rds -> cloud_db3}
        {rank=same; aurora -> cloud_db4}
        {rank=same; dynamo_db -> cloud_db5}

        # Search Engines
        elastic_search [label="ElasticSearch"]
        solr [label="Solr"]
        sphinx [label="Sphinx"]

        search1 -> search2 -> search3

        {rank=same; search1 -> search_engine}
        {rank=same; elastic_search -> search1}
        {rank=same; solr -> search2}
        {rank=same; sphinx -> search3}

        # NoSQL
        mongo_db [label="MongoDB"]
        redis [label="Redis"]
        lite_db [label="LiteDB"]
        cassandra [label="Apache Cassandra"]
        raven_db [label="RavenDB"]
        couch_db [label="CouchDB"]

        no_sql1 -> no_sql2 -> no_sql3 -> no_sql4 -> no_sql5 -> no_sql6

        {rank=same; no_sql1 -> no_sql}
        {rank=same; mongo_db -> no_sql1}
        {rank=same; redis -> no_sql2}
        {rank=same; lite_db -> no_sql3}
        {rank=same; cassandra -> no_sql4}
        {rank=same; raven_db -> no_sql5}
        {rank=same; couch_db -> no_sql6}
    }

    subgraph chaching_group{
        caching [label="Caching"]
        ef_cache [label="Entity Framework 2nd Level Cache"]
        distributed_cache [label="Distributed Cache"]
        memory_cache [label="Memory Cache"]

        caching1 -> caching2 -> caching3

        {rank=same; caching -> caching1 [minlen=5]}
        #{rank=same; caching1 -> ef_cache}
        #{rank=same; caching2 -> distributed_cache}
        #{rank=same; caching3 -> memory_cache}
    }
}


Here is the output.

enter image description here

As you can see, I can't make the caching node on the right-hand side or the main edge and it also interrupts database node.

If you have any ideas to fix this, please let me know. Thank you so much.

FYI The tool I use: Graphviz Preview VS Code plugin and Graphviz engine version 2.38.0.20190211

enter image description here

1 Answers

You need some scaffolding i.e. extra invisible nodes and/or edges

try add the following at the end:

{rank=same  db2->main10[minlen=5 color=invis]}
Related