Based on my previous post, Thomas Frisendal challenged me (and everyone else) on Twitter to do the following:

  • Save a CmapTools concept map as “CXL” (XML)
  • Load it into Neo4j using the APOC library
  • Transform it to a graph metamodel using Cypher
  • Generate Cypher “DDL”

The last part he clarified in a separate tweet:

@srobijns Hi Sander, I mean getting to a stage where you can easily generate “template” cypher commands for populating the data base. Could be by way of excel or some clever cypher construct. But not the most important part of it. Getting a data model in shape as metadata is the real job.

Introduction

Let me first start by saying that I have no experience at all with Neo4j, Cypher or the APOC library. It was a journey of trial and error and the final result works, but can most likely be optimized and/or achieved in more clever ways.

I decided to use the “Curriculum Vitae” concept map from the previous post as the one to be converted to a graph metamodel.

The thinking and discovery

Having accepted the challenge, I started looking at the Neo4j documentation and the APOC documentation. Based on my initial reading, I structured my thoughts in a concept map in CmapTools, which you can view online or below:

The main takeaways are:

  • A graph database like Neo4j doesn’t support a strong explicit schema like an RDBMS
  • Neo4j does offer certain types of constraints to be added, but some of them are only available in the enterprise edition and I don’t have that:
    > Property existence constraints and Node Keys are only available in Neo4j Enterprise Edition. Note that databases with property existence constraints and/or Node Keys cannot be opened using Neo4j Community Edition.

Down the line, I discovered the following things indicating my initial thoughts were not entirely correct (but I didn’t bother to update the concept map):

  • A virtual graph is indeed virtual and not persisted in any way. It lives within the context of the query you run and can be visualized and processed at that time, but can’t be used as a template to be used as a “schema” unless it’s being build every time. Conclusion: virtual graphs are not useful here;
  • For whatever reason exactly, I could not get the XPath stuff to work with the apoc.load.xml function;
  • Standard Cypher does not allow to dynamically add a label to a node. You need to use the APOC library;
  • Edges (relationships) can only have one label (nodes can have multiple);
  • The XML structure of the CmapTools concept map was not exactly what I expected it to be. A “linking phrase” between two concepts is a kind of meta-concept that has two connections, one from its originating concept and one to its target concept. Taken the following proposition from the concept map Language is spoken in Country, this results in the following parts in the XML:
<concept id="PF26MG1N-BX9PVR-21" label="Language"/>
<concept id="BHHZLG1N-TF9FWD-5" label="Country"/>
<linking-phrase id="HQT9MG1N-B979042-F1" label="spoken in"/>
<connection id="LQT9MG1N-X034JK3-G1" from-id="PF26MG1N-BX9PVR-21" to-id="HQT9MG1N-B979042-F1"/>
<connection id="MQT9MG1N-RZCBP02-H1" from-id="HQT9MG1N-B979042-F1" to-id="BHHZLG1N-TF9FWD-5"/>

Visually this becomes (apart from the fact that the lines – i.e. connection in the XML – don’t have a label assigned):

Steps taken

Step 1: Save a CmapTools concept map as “CXL” (XML)

This is easy and I won’t go into the details of it. I did rename the output file (with extension .CXL) into one with extension “.XML”.

The entire contents of the file is the following:

<?xml version="1.0" encoding="UTF-8"?>
<cmap xmlns:dcterms="http://purl.org/dc/terms/" xmlns="http://cmap.ihmc.us/xml/cmap/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#">
    <res-meta>
        <dc:title>Curriculum Vitae</dc:title>
        <dc:description>Which concepts play a role when defining a curriculum vitae?</dc:description>
        <dc:creator>
            <vcard:FN>Sander Robijns</vcard:FN>
            <vcard:EMAIL>sander.robijns@gmail.com</vcard:EMAIL>
        </dc:creator>
        <dc:contributor>
            <vcard:FN>Sander Robijns</vcard:FN>
            <vcard:EMAIL>sander.robijns@gmail.com</vcard:EMAIL>
        </dc:contributor>
        <dcterms:rightsHolder>
            <vcard:FN>Sander Robijns</vcard:FN>
            <vcard:EMAIL>sander.robijns@gmail.com</vcard:EMAIL>
        </dcterms:rightsHolder>
        <dcterms:created>2018-06-13T22:04:10+02:00</dcterms:created>
        <dcterms:modified>2018-06-14T00:13:10+02:00</dcterms:modified>
        <dc:language>en</dc:language>
        <dc:format>x-cmap/x-storable</dc:format>
        <dc:publisher>FIHMC CmapTools 6.03</dc:publisher>
        <dc:extent>167834 bytes</dc:extent>
        <dc:source>cmap:1MHZH5RK6-2C8DRLF-1:uid=6bb0ab4c-6af5-4d57-8559-401997034da4,ou=users,dc=cmapcloud,dc=ihmc,dc=us:N71XLG1N-QYSTTT4-1</dc:source>
    </res-meta>
    <map width="659" height="598">
        <concept-list>
            <concept id="K8Z8RG1N-LSKW9K2-F4" label="Vacancy"/>
            <concept id="2GY8NG1N-VD526S2-P2" label="Organisation"/>
            <concept id="FG69RG1N-02TLMQ-J4" label="Assignment"/>
            <concept id="VR40NG1N-KL3TRL1-Z1" label="Education"/>
            <concept id="K0XRMG1N-DX4R742-L1" label="Skill"/>
            <concept id="BHHZLG1N-TF9FWD-5" label="Country"/>
            <concept id="8ZHTMG1N-XKK6YB4-P1" label="Role"/>
            <concept id="HZ6PTG1N-H012R32-49" label="Hobby"/>
            <concept id="4P2YLG1N-KJCW6K4-2" label="Person"/>
            <concept id="PF26MG1N-BX9PVR-21" label="Language"/>
            <concept id="Z46FNG1N-0X3DGJ-V2" label="Sector"/>
        </concept-list>
        <linking-phrase-list>
            <linking-phrase id="TN1YTG1N-1JDDNH4-V9" label="requires"/>
            <linking-phrase id="Z4RKVG1N-758NJP1-5B" label="lives in"/>
            <linking-phrase id="HQT9MG1N-B979042-F1" label="spoken in"/>
            <linking-phrase id="P1WWQG1N-5FBTT52-K3" label="located in"/>
            <linking-phrase id="6XK3NG1N-YD3QBY1-52" label="teaches"/>
            <linking-phrase id="8R4RQG1N-81XLGV3-83" label="operates in"/>
            <linking-phrase id="X1Q6TG1N-MWTV944-18" label="applies for"/>
            <linking-phrase id="HTZ8SG1N-02D0GB2-T5" label="used in"/>
            <linking-phrase id="64V5SG1N-R91TQ33-M5" label="used in"/>
            <linking-phrase id="0W0HSG1N-FJBM2V1-36" label="for"/>
            <linking-phrase id="ZKCWMG1N-C6FV9Q3-S1" label="posseses"/>
            <linking-phrase id="7GSSTG1N-S7SYKJ1-F9" label="has"/>
            <linking-phrase id="L3Z4NG1N-LC38XX2-B2" label="followed"/>
            <linking-phrase id="2PJKTG1N-6DR2XS3-Y8" label="requires"/>
            <linking-phrase id="XH3NSG1N-HBF2FW3-L6" label="used in"/>
            <linking-phrase id="YYPTRG1N-00011T2-15" label="results in"/>
            <linking-phrase id="6ZWZLG1N-MV8VT4-9" label="wants to work in"/>
            <linking-phrase id="VT55SG1N-FXFYD53-F5" label="used in"/>
            <linking-phrase id="3S77MG1N-FYDYMQ3-81" label="learned"/>
            <linking-phrase id="GLLHSG1N-QMPK12-96" label="requires"/>
            <linking-phrase id="WYFDRG1N-3772SZ1-S4" label="has"/>
            <linking-phrase id="CKC5RG1N-XBN9RF3-64" label="prefers"/>
            <linking-phrase id="6WD1RG1N-48RM2P1-W3" label="has domain 
knowledge of "/>
            <linking-phrase id="FDQZRG1N-1XZCKS-65" label="assigned to"/>
        </linking-phrase-list>
        <connection-list>
            <connection id="LQT9MG1N-X034JK3-G1" from-id="PF26MG1N-BX9PVR-21" to-id="HQT9MG1N-B979042-F1"/>
            <connection id="R1WWQG1N-4895674-L3" from-id="2GY8NG1N-VD526S2-P2" to-id="P1WWQG1N-5FBTT52-K3"/>
            <connection id="9WD1RG1N-8P3T371-X3" from-id="4P2YLG1N-KJCW6K4-2" to-id="6WD1RG1N-48RM2P1-W3"/>
            <connection id="FKC5RG1N-FT86FR2-74" from-id="4P2YLG1N-KJCW6K4-2" to-id="CKC5RG1N-XBN9RF3-64"/>
            <connection id="1LCWMG1N-75TW6K3-T1" from-id="4P2YLG1N-KJCW6K4-2" to-id="ZKCWMG1N-C6FV9Q3-S1"/>
            <connection id="8ZWZLG1N-THN8J14-B" from-id="4P2YLG1N-KJCW6K4-2" to-id="6ZWZLG1N-MV8VT4-9"/>
            <connection id="N3Z4NG1N-5QM3QG2-D2" from-id="L3Z4NG1N-LC38XX2-B2" to-id="VR40NG1N-KL3TRL1-Z1"/>
            <connection id="HLLHSG1N-WG87QK1-B6" from-id="K8Z8RG1N-LSKW9K2-F4" to-id="GLLHSG1N-QMPK12-96"/>
            <connection id="9R4RQG1N-PJ5CBM3-93" from-id="2GY8NG1N-VD526S2-P2" to-id="8R4RQG1N-81XLGV3-83"/>
            <connection id="4PJKTG1N-8Q6V294-Z8" from-id="8ZHTMG1N-XKK6YB4-P1" to-id="2PJKTG1N-6DR2XS3-Y8"/>
            <connection id="2LCWMG1N-2539W23-V1" from-id="ZKCWMG1N-C6FV9Q3-S1" to-id="K0XRMG1N-DX4R742-L1"/>
            <connection id="B53RSG1N-PYF6TR-T6" from-id="GLLHSG1N-QMPK12-96" to-id="VR40NG1N-KL3TRL1-Z1"/>
            <connection id="Z1Q6TG1N-2WLJ194-28" from-id="4P2YLG1N-KJCW6K4-2" to-id="X1Q6TG1N-MWTV944-18"/>
            <connection id="YT55SG1N-YH46D11-H5" from-id="VT55SG1N-FXFYD53-F5" to-id="FG69RG1N-02TLMQ-J4"/>
            <connection id="6PJKTG1N-1QFPX6-09" from-id="2PJKTG1N-6DR2XS3-Y8" to-id="K0XRMG1N-DX4R742-L1"/>
            <connection id="BXK3NG1N-B4S0452-62" from-id="VR40NG1N-KL3TRL1-Z1" to-id="6XK3NG1N-YD3QBY1-52"/>
            <connection id="CGSSTG1N-S9G2N62-H9" from-id="7GSSTG1N-S7SYKJ1-F9" to-id="HZ6PTG1N-H012R32-49"/>
            <connection id="S1WWQG1N-6DKZ26-M3" from-id="P1WWQG1N-5FBTT52-K3" to-id="BHHZLG1N-TF9FWD-5"/>
            <connection id="1ZPTRG1N-0N6WFG3-35" from-id="YYPTRG1N-00011T2-15" to-id="FG69RG1N-02TLMQ-J4"/>
            <connection id="94V5SG1N-TFHTH64-N5" from-id="K0XRMG1N-DX4R742-L1" to-id="64V5SG1N-R91TQ33-M5"/>
            <connection id="GXK3NG1N-V0HXCS4-72" from-id="6XK3NG1N-YD3QBY1-52" to-id="K0XRMG1N-DX4R742-L1"/>
            <connection id="9GSSTG1N-8JBLCT-G9" from-id="4P2YLG1N-KJCW6K4-2" to-id="7GSSTG1N-S7SYKJ1-F9"/>
            <connection id="4S77MG1N-V27GGL2-91" from-id="4P2YLG1N-KJCW6K4-2" to-id="3S77MG1N-FYDYMQ3-81"/>
            <connection id="MQT9MG1N-RZCBP02-H1" from-id="HQT9MG1N-B979042-F1" to-id="BHHZLG1N-TF9FWD-5"/>
            <connection id="JDQZRG1N-HFZDLR1-85" from-id="FDQZRG1N-1XZCKS-65" to-id="FG69RG1N-02TLMQ-J4"/>
            <connection id="B4V5SG1N-9KLD943-P5" from-id="64V5SG1N-R91TQ33-M5" to-id="FG69RG1N-02TLMQ-J4"/>
            <connection id="9ZWZLG1N-CGHWHH3-C" from-id="6ZWZLG1N-MV8VT4-9" to-id="BHHZLG1N-TF9FWD-5"/>
            <connection id="XT55SG1N-TKC86H2-G5" from-id="8ZHTMG1N-XKK6YB4-P1" to-id="VT55SG1N-FXFYD53-F5"/>
            <connection id="15RKVG1N-FDN9TF3-6B" from-id="4P2YLG1N-KJCW6K4-2" to-id="Z4RKVG1N-758NJP1-5B"/>
            <connection id="WN1YTG1N-9GZRPB1-W9" from-id="HZ6PTG1N-H012R32-49" to-id="TN1YTG1N-1JDDNH4-V9"/>
            <connection id="5W0HSG1N-21QGR64-46" from-id="K8Z8RG1N-LSKW9K2-F4" to-id="0W0HSG1N-FJBM2V1-36"/>
            <connection id="CR4RQG1N-CPN5L42-B3" from-id="8R4RQG1N-81XLGV3-83" to-id="Z46FNG1N-0X3DGJ-V2"/>
            <connection id="ZH3NSG1N-N03FLK-M6" from-id="PF26MG1N-BX9PVR-21" to-id="XH3NSG1N-HBF2FW3-L6"/>
            <connection id="6W0HSG1N-MF2DJ52-56" from-id="0W0HSG1N-FJBM2V1-36" to-id="8ZHTMG1N-XKK6YB4-P1"/>
            <connection id="JLLHSG1N-68PW6K2-C6" from-id="GLLHSG1N-QMPK12-96" to-id="K0XRMG1N-DX4R742-L1"/>
            <connection id="YYFDRG1N-8D8W8B3-T4" from-id="2GY8NG1N-VD526S2-P2" to-id="WYFDRG1N-3772SZ1-S4"/>
            <connection id="0ZPTRG1N-WP4Y5X3-25" from-id="K8Z8RG1N-LSKW9K2-F4" to-id="YYPTRG1N-00011T2-15"/>
            <connection id="ZYFDRG1N-0SGYMQ-V4" from-id="WYFDRG1N-3772SZ1-S4" to-id="K8Z8RG1N-LSKW9K2-F4"/>
            <connection id="02Q6TG1N-L7YP8T3-38" from-id="X1Q6TG1N-MWTV944-18" to-id="K8Z8RG1N-LSKW9K2-F4"/>
            <connection id="6S77MG1N-SYZCZ6-B1" from-id="3S77MG1N-FYDYMQ3-81" to-id="PF26MG1N-BX9PVR-21"/>
            <connection id="WN1YTG1N-8DKXQB2-X9" from-id="TN1YTG1N-1JDDNH4-V9" to-id="K0XRMG1N-DX4R742-L1"/>
            <connection id="KTZ8SG1N-PV0YT9-V5" from-id="2GY8NG1N-VD526S2-P2" to-id="HTZ8SG1N-02D0GB2-T5"/>
            <connection id="M3Z4NG1N-8L26LM1-C2" from-id="4P2YLG1N-KJCW6K4-2" to-id="L3Z4NG1N-LC38XX2-B2"/>
            <connection id="25RKVG1N-C8MYGH4-7B" from-id="Z4RKVG1N-758NJP1-5B" to-id="BHHZLG1N-TF9FWD-5"/>
            <connection id="MTZ8SG1N-8MTL6F-W5" from-id="HTZ8SG1N-02D0GB2-T5" to-id="FG69RG1N-02TLMQ-J4"/>
            <connection id="HDQZRG1N-DYSQJF3-75" from-id="4P2YLG1N-KJCW6K4-2" to-id="FDQZRG1N-1XZCKS-65"/>
            <connection id="6FKWTG1N-1ZDPWZ3-R9" from-id="6XK3NG1N-YD3QBY1-52" to-id="PF26MG1N-BX9PVR-21"/>
            <connection id="GKC5RG1N-J9CN7R1-84" from-id="CKC5RG1N-XBN9RF3-64" to-id="8ZHTMG1N-XKK6YB4-P1"/>
            <connection id="DWD1RG1N-QPJ5NM3-Y3" from-id="6WD1RG1N-48RM2P1-W3" to-id="Z46FNG1N-0X3DGJ-V2"/>
            <connection id="0J3NSG1N-Z5L5323-N6" from-id="XH3NSG1N-HBF2FW3-L6" to-id="2GY8NG1N-VD526S2-P2"/>
        </connection-list>
        <concept-appearance-list>
            <concept-appearance id="K8Z8RG1N-LSKW9K2-F4" x="594" y="642" width="68" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="2GY8NG1N-VD526S2-P2" x="663" y="426" width="90" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="FG69RG1N-02TLMQ-J4" x="479" y="538" width="85" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="VR40NG1N-KL3TRL1-Z1" x="133" y="253" width="75" height="31" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="K0XRMG1N-DX4R742-L1" x="301" y="398" width="44" height="31" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="BHHZLG1N-TF9FWD-5" x="720" y="254" width="64" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="8ZHTMG1N-XKK6YB4-P1" x="390" y="448" width="47" height="31" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="HZ6PTG1N-H012R32-49" x="273" y="253" width="57" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="4P2YLG1N-KJCW6K4-2" x="386" y="78" width="60" height="31" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="PF26MG1N-BX9PVR-21" x="559" y="252" width="75" height="33" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
            <concept-appearance id="Z46FNG1N-0X3DGJ-V2" x="537" y="325" width="57" height="31" font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" background-image-style="full"
                border-color="3,127,140,255" border-style="solid" border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
        </concept-appearance-list>
        <linking-phrase-appearance-list>
            <linking-phrase-appearance id="TN1YTG1N-1JDDNH4-V9" x="285" y="338" width="45" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="Z4RKVG1N-758NJP1-5B" x="589" y="108" width="39" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="HQT9MG1N-B979042-F1" x="636" y="251" width="53" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="P1WWQG1N-5FBTT52-K3" x="690" y="341" width="53" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="6XK3NG1N-YD3QBY1-52" x="224" y="329" width="44" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="8R4RQG1N-81XLGV3-83" x="574" y="376" width="61" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="X1Q6TG1N-MWTV944-18" x="488" y="382" width="57" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="HTZ8SG1N-02D0GB2-T5" x="581" y="477" width="41" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="64V5SG1N-R91TQ33-M5" x="350" y="507" width="41" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="0W0HSG1N-FJBM2V1-36" x="430" y="585" width="16" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="ZKCWMG1N-C6FV9Q3-S1" x="343" y="251" width="53" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="7GSSTG1N-S7SYKJ1-F9" x="317" y="172" width="21" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="L3Z4NG1N-LC38XX2-B2" x="234" y="154" width="46" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="2PJKTG1N-6DR2XS3-Y8" x="350" y="422" width="45" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="XH3NSG1N-HBF2FW3-L6" x="614" y="340" width="41" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="YYPTRG1N-00011T2-15" x="536" y="593" width="50" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="6ZWZLG1N-MV8VT4-9" x="568" y="154" width="88" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="VT55SG1N-FXFYD53-F5" x="423" y="488" width="41" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="3S77MG1N-FYDYMQ3-81" x="523" y="188" width="42" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="GLLHSG1N-QMPK12-96" x="282" y="573" width="45" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="WYFDRG1N-3772SZ1-S4" x="626" y="532" width="21" height="11" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="CKC5RG1N-XBN9RF3-64" x="380" y="389" width="39" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="6WD1RG1N-48RM2P1-W3" x="478" y="224" width="76" height="27" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
            <linking-phrase-appearance id="FDQZRG1N-1XZCKS-65" x="432" y="404" width="63" height="13" font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" background-image-style="full"
                border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
        </linking-phrase-appearance-list>
        <connection-appearance-list>
            <connection-appearance id="LQT9MG1N-X034JK3-G1" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="R1WWQG1N-4895674-L3" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="9WD1RG1N-8P3T371-X3" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="FKC5RG1N-FT86FR2-74" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="1LCWMG1N-75TW6K3-T1" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="8ZWZLG1N-THN8J14-B" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="N3Z4NG1N-5QM3QG2-D2" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="HLLHSG1N-WG87QK1-B6" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="9R4RQG1N-PJ5CBM3-93" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="4PJKTG1N-8Q6V294-Z8" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="2LCWMG1N-2539W23-V1" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="B53RSG1N-PYF6TR-T6" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="Z1Q6TG1N-2WLJ194-28" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="YT55SG1N-YH46D11-H5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="6PJKTG1N-1QFPX6-09" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="BXK3NG1N-B4S0452-62" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="CGSSTG1N-S9G2N62-H9" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="S1WWQG1N-6DKZ26-M3" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="1ZPTRG1N-0N6WFG3-35" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="94V5SG1N-TFHTH64-N5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="GXK3NG1N-V0HXCS4-72" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="9GSSTG1N-8JBLCT-G9" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="4S77MG1N-V27GGL2-91" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="MQT9MG1N-RZCBP02-H1" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="JDQZRG1N-HFZDLR1-85" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="B4V5SG1N-9KLD943-P5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="9ZWZLG1N-CGHWHH3-C" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="XT55SG1N-TKC86H2-G5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="15RKVG1N-FDN9TF3-6B" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="WN1YTG1N-9GZRPB1-W9" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="5W0HSG1N-21QGR64-46" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="CR4RQG1N-CPN5L42-B3" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="ZH3NSG1N-N03FLK-M6" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="6W0HSG1N-MF2DJ52-56" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="JLLHSG1N-68PW6K2-C6" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="YYFDRG1N-8D8W8B3-T4" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="0ZPTRG1N-WP4Y5X3-25" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="ZYFDRG1N-0SGYMQ-V4" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="02Q6TG1N-L7YP8T3-38" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="6S77MG1N-SYZCZ6-B1" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="WN1YTG1N-8DKXQB2-X9" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="KTZ8SG1N-PV0YT9-V5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="M3Z4NG1N-8L26LM1-C2" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="25RKVG1N-C8MYGH4-7B" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="MTZ8SG1N-8MTL6F-W5" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="HDQZRG1N-DYSQJF3-75" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="6FKWTG1N-1ZDPWZ3-R9" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="GKC5RG1N-J9CN7R1-84" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="DWD1RG1N-QPJ5NM3-Y3" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            <connection-appearance id="0J3NSG1N-Z5L5323-N6" from-pos="center" to-pos="center" color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
        </connection-appearance-list>
        <style-sheet-list>
            <style-sheet id="_Default_">
                <map-style background-color="238,238,238,0" image-style="full" image-top-left="0,0"/>
                <concept-style font-name="Verdana" font-size="12" font-style="plain" font-color="0,0,0,255" text-margin="4" background-color="250,248,211,255" background-image-style="full" border-color="200,200,200,255" border-style="solid"
                    border-thickness="2" border-shape="rounded-rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
                <linking-phrase-style font-name="Verdana" font-size="12" font-style="plain" font-color="0,0,0,255" text-margin="1" background-color="0,0,255,0" background-image-style="full" border-color="0,0,0,255" border-style="none" border-thickness="1"
                    border-shape="rectangle" text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
                <connection-style color="0,0,0,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept-and-slopes-up"/>
            </style-sheet>
            <style-sheet id="_LatestChanges_">
                <concept-style font-name="Arial" font-size="12" font-style="plain" font-color="10,33,64,255" text-margin="4" background-color="255,255,255,255" border-color="3,127,140,255" border-style="solid" border-thickness="2"
                    border-shape="rounded-rectangle" text-alignment="center" shadow-color="29,31,34,255" min-width="-1" min-height="-1"/>
                <linking-phrase-style font-name="Arial" font-size="12" font-style="plain" font-color="8,52,52,255" text-margin="1" background-color="0,0,255,0" border-color="0,0,0,255" border-style="none" border-thickness="1" border-shape="rectangle"
                    text-alignment="center" shadow-color="none" min-width="-1" min-height="-1"/>
                <connection-style color="121,18,37,255" style="solid" thickness="1" type="straight" arrowhead="if-to-concept"/>
            </style-sheet>
        </style-sheet-list>
        <extra-graphical-properties-list>
            <properties-list id="N71XLG1N-QYSTTT4-1">
                <property key="StyleSheetGroup_0" value="//*@!#$%%^&*()() No Grouped StyleSheets @"/>
            </properties-list>
        </extra-graphical-properties-list>
    </map>
</cmap>

Step 2: Load it into Neo4j using the APOC library

To enable loading using the APOC library, the following must be added to your neo4j.conf config file:

apoc.import.file.enabled=true

After a lot of various trial and error, I came up with the following Cypher/APOC code to load the concept map XML file into Neo4j:

call apoc.load.xml('file:///Users/sanderrobijns/Documents/cv.xml'
) yield value as cmap
unwind cmap._children as child
with child
unwind child._children as list
with list
where (list._type IN ['concept-list', 'linking-phrase-list', 'connection-list'])
unwind list._children as item
with item
call apoc.create.node([case when item.label is not null then item.label else item._type end, item._type], {_id:item.id, name:case when item.label is not null then item.label else item._type end, _from:case when item.from-id is not null then item.from-id else '' end, _to:case when item.to-id is not null then item.to-id else '' end}) yield node
return *

Given the structure of the concept map’s XML, the cmap is the top level. Below that are two first level ones, res-meta and map. The first unwind takes care of that.
Within map, we find the only collections of interest are the concept-list, linking-phrase-list and connection-list. The other collections are used for representation in the CmapTools. The second unwind together with the “with list where…” takes care of that.
Each of the collections selected contain the actual items of interest, which the last unwind takes care of.
Then, the nodes are being created using an APOC call, because that is the only way that dynamically created labels can be attached to a node. Within the call, I use case statements for both the label and the properties of the node, keeping the following in mind:

  • both a concept and a linking-phrase have an id and a label in the concept map, but connection has no label
  • a connection has a from-id and to-id but the others have not

The reason for the single quotes around from-id and to-id are because of the fact that Neo4j can’t handle variables with a hyphen.

In the end, the following is true:

  • a concept and linking-phrase will have its label property (from the XML) set as its label in Neo4j (i.e. the type) for the node created
  • a concept and linking-phrase_will have its _label property (from the XML) set as the name property of the node
  • a connection will have its type set as its label in Neo4j (i.e. the type, i.e. the literal string “connection”)
  • a connection node will have it’s _from and _to properties set with the values defined in from-id and to-id respectively
  • all nodes have a property id set with the value of the id in the concept map

The result of this is not very useful yet, as there are no edges between the nodes. The connection and _linking phrase_nodes are the ones that need to be converted to actual relationships:

Step 3: Transform it to a graph metamodel using Cypher

Transforming the initial load of the concept map into a graph metamodel consists of several substeps:

  1. Create relationships between the concepts and linking-phrases;
  2. Create relationships between the originating and target concept, bypassing the linking-phrase node in the middle;
  3. Remove the connection nodes;
  4. Remove the linking-phrase nodes and their relationships;
  5. Remove the concept label and properties (except name) from the nodes.

Create relationships between the concepts and linking-phrases

The code:

match (r:connection),(f),(t)
where f._id = r._from and t._id = r._to
call apoc.create.relationship(f, toUpper(replace(t.name, ' ', '_')), {}, t) yield rel
return *

Using the connection nodes and their _from and _to properties, they are linked to their corresponding concept and linking-phrase nodes in the “where”-clause of the query.
Next, a new relationship is created using APOC due to the fact that this is the only way to dynamically assign the label to the relationship. At the same time, the relationship name is converted to uppercase and spaces are replaced by underscores to comply with the suggested naming conventions in Neo4j.

This results in the following, in which you can see that the connection nodes are not related to anything and basically have lost their use. I will get rid of them later.

Create relationships between the originating and target concept, bypassing the linking-phrase node in the middle

Remember that the linking-phrase is actually a node in the middle of two concept nodes, like this:

But that is not what we want. We want to replace the linking-phrase with a direct relationship between the concept nodes. The following code creates those direct relationships:

match (f:concept)-[r]->(l:linking-phrase)-[]->(t:concept)
call apoc.create.relationship(f, type(r), {}, t) yield rel
return rel

First, we match all paths like in the picture above. The second relationship (“COUNTRY” in the example above) is not of interest, only the first, so that’s why there is no variable assigned to it.
Then the relationship is created between the two concept nodes using the APOC library again, so that the label can be set dynamically. This bypasses the linking-phrase node in the middle.
The reason for the single quotes around linking-phrase is because of the fact that Neo4j can’t deal with variables with a hyphen in them.

The result looks like this, which is the same representation as the original concept map (albeit different colors and not in the same positions):

However, we are not done yet. We still have connection nodes, linking-phrase nodes and properties that we no longer need.

Remove the connection nodes

As the connection nodes are no longer needed and not attached to anything, we can delete them with the following statement:

match (n:connection) delete n

Remove the linking-phrase nodes and their relationships

As the linking-phrase nodes are no longer needed, we can delete them with the following statement. The “detach” is needed because of the relationships that are present between the linking-phrase and concept nodes.

match (n:`linking-phrase`) detach delete n

Remove the concept label and properties (except name) from the nodes

At this point, we don’t care anymore about the nodes have the (Neo4j) label concept. It would be nice to keep it if we could also have multiple labels assigned to relationships, but that’s not the case. We also don’t care anymore about the _from, _to and _id properties, so all is removed with the following statement:

match (n:concept)
remove n:concept, n._from, n._to, n._id
return n

Step 4: Generate Cypher “DDL”

This is the hard part and I haven’t had the time yet to think it over in all detail. Things that come to mind to experiment with:

  • Using triggers (both standard and from the APOC library)
  • Using constraints (as far as supported in the community edition of Neo4j)
  • Parsing propositions with some kind of matching, i.e. Sander lives in The Netherlands would need to translate to the following Cypher code:
merge path=(p:Person {name: "Sander"})-[r:LIVES_IN]->(c:Country {name: "The Netherlands"})
return path

However, this will be for another time. Stay tuned!

Leave a Reply

%d bloggers like this: