Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Round trip with apoc graphml coerces types to string #35

Closed
neo-technology-build-agent opened this issue Sep 1, 2022 · 2 comments
Closed

Comments

@neo-technology-build-agent
Copy link
Collaborator

Issue by Rosswart
Tuesday Jul 20, 2021 at 10:03 GMT
Originally opened as neo4j-contrib/neo4j-apoc-procedures#2099


Expected Behavior

Exporting a graph with

    CALL apoc.export.graphml.all('types.graphml', {useTypes: true, storeNodeIds: false})

into graphml

    <?xml version="1.0" encoding="UTF-8"?>
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="b" for="node" attr.name="b" attr.type="string"/>
    <key id="c" for="node" attr.name="c" attr.type="string" attr.list="string"/>
    <key id="d" for="node" attr.name="d" attr.type="long"/>
    <graph id="G" edgedefault="directed">
    <node id="n0"><data key="a">string</data><data key="b">string</data></node>
    <node id="n1"><data key="a">string</data><data key="b">string</data></node>
    <node id="n2"><data key="a">["array","string"]</data><data key="c">["array","string"]</data></node>
    <node id="n3"><data key="a">["array","string"]</data><data key="c">["array","string"]</data></node>
    <node id="n4"><data key="a">123</data><data key="d">123</data></node>
    <node id="n5"><data key="a">123</data><data key="d">123</data></node>
    </graph>
    </graphml>

and then importing this again with

    CALL apoc.import.graphml('types.graphml', {readLabels: true})

should reproduce the same graph

    MATCH (n)
    RETURN
      apoc.meta.type(n.a), n.a,
      apoc.meta.type(n.b), n.b,
      apoc.meta.type(n.c), n.c,
      apoc.meta.type(n.d), n.d

with all properties having the same type as in the original graph:

    ╒═════════════════════╤══════════════════╤═════════════════════╤════════╤═════════════════════╤══════════════════╤═════════════════════╤═════╕
    │"apoc.meta.type(n.a)"│"n.a"             │"apoc.meta.type(n.b)"│"n.b"   │"apoc.meta.type(n.c)"│"n.c"             │"apoc.meta.type(n.d)"│"n.d"│
    ╞═════════════════════╪══════════════════╪═════════════════════╪════════╪═════════════════════╪══════════════════╪═════════════════════╪═════╡
    │"STRING"             │"string"          │"STRING"             │"string"│"NULL"               │null              │"NULL"               │null │
    ├─────────────────────┼──────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"string"          │"STRING"             │"string"│"NULL"               │null              │"NULL"               │null │
    ├─────────────────────┼──────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"String[]"           │["array","string"]│"NULL"               │null    │"String[]"           │["array","string"]│"NULL"               │null │
    ├─────────────────────┼──────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"String[]"           │["array","string"]│"NULL"               │null    │"String[]"           │["array","string"]│"NULL"               │null │
    ├─────────────────────┼──────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"INTEGER"            │123               │"NULL"               │null    │"NULL"               │null              │"INTEGER"            │123  │
    ├─────────────────────┼──────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"INTEGER"            │123               │"NULL"               │null    │"NULL"               │null              │"INTEGER"            │123  │
    └─────────────────────┴──────────────────┴─────────────────────┴────────┴─────────────────────┴──────────────────┴─────────────────────┴─────┘

Actual Behavior

If the original node properties are of mixed type (see "n.a"), then the imported properties are coerced to string. All properties with pure types do have the original type.

    ╒═════════════════════╤════════════════════╤═════════════════════╤════════╤═════════════════════╤══════════════════╤═════════════════════╤═════╕
    │"apoc.meta.type(n.a)"│"n.a"               │"apoc.meta.type(n.b)"│"n.b"   │"apoc.meta.type(n.c)"│"n.c"             │"apoc.meta.type(n.d)"│"n.d"│
    ╞═════════════════════╪════════════════════╪═════════════════════╪════════╪═════════════════════╪══════════════════╪═════════════════════╪═════╡
    │"STRING"             │"string"            │"STRING"             │"string"│"NULL"               │null              │"NULL"               │null │
    ├─────────────────────┼────────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"string"            │"STRING"             │"string"│"NULL"               │null              │"NULL"               │null │
    ├─────────────────────┼────────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"["array","string"]"│"NULL"               │null    │"String[]"           │["array","string"]│"NULL"               │null │
    ├─────────────────────┼────────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"["array","string"]"│"NULL"               │null    │"String[]"           │["array","string"]│"NULL"               │null │
    ├─────────────────────┼────────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"123"               │"NULL"               │null    │"NULL"               │null              │"INTEGER"            │123  │
    ├─────────────────────┼────────────────────┼─────────────────────┼────────┼─────────────────────┼──────────────────┼─────────────────────┼─────┤
    │"STRING"             │"123"               │"NULL"               │null    │"NULL"               │null              │"INTEGER"            │123  │
    └─────────────────────┴────────────────────┴─────────────────────┴────────┴─────────────────────┴──────────────────┴─────────────────────┴─────┘

How to Reproduce the Problem

Simple Dataset

    CREATE ({a: "string",           b: "string"})
    CREATE ({a: "string",           b: "string"})
    CREATE ({a: ["array", "string", c: ["array", "string"]]})
    CREATE ({a: ["array", "string", c: ["array", "string"]]})
    CREATE ({a: 123,                d: 123})
    CREATE ({a: 123,                d: 123})

Steps (Mandatory)

  1. Create graph
  2. Export
  3. Import

Specifications

Versions

  • OS: Windows 10 Enterprise 10.0.17763 Build 17763
  • Neo4j: neo4j-3.5.28
  • Neo4j-Apoc: apoc-3.5.0.15
@hvub
Copy link
Collaborator

hvub commented Nov 18, 2024

This behavior is due to a restriction of GraphML. GraphML assumes that all node or relationship properties with the same property name have property value of the same type. Neo4j allows mixed types per property name. If a property name has value of mixed value types, then its value are exported as a STRING.

If a node property name is associated with property value of different types, e.g. as in (:LabelA {prop: 123}), (:LabelB {prop: 'abc'}) or as in the example above, then no property type information is written to the graphml output for that node property name. The same holds for relationship properties.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants