majensen / perlbolt

Neo4j server agent using Bolt protocol
Apache License 2.0
4 stars 2 forks source link

Paths are returned as array references #11

Closed johannessen closed 4 years ago

johannessen commented 4 years ago

Consider the following two statements:

CREATE p=()<-[:REL]-() RETURN p
CREATE (a)<-[b:REL]-(c) RETURN [a,b,c] AS p

As you can see, the first statement returns a named path, the second a list – which are, of course, separate data types in Neo4j.

However, when run through Neo4j::Bolt, the two queries produce exactly the same output (well, except that the IDs are different, obviously):

[
    { _node => 100 },
    { _relationship => 10, _type => 'REL', _start => 101, _end => 100 },
    { _node => 101 },
]

Right now I’m finally working on the type system for Neo4j::Driver. The above structure will always be treated as a list.

Because my goal is to implement the Neo4j Driver API, which returns paths as typed objects, I need to be able to tell paths apart from arrays in the response from the Neo4j server. Therefore, the current implementation of Neo4j::Bolt::TypeHandlersC->neo4j_path_to_AV doesn’t work for me.

Fundamentally, this is issue is similar to #5 insofar as the meta data that Neo4j::Bolt passes on to its clients is insufficient to handle certain edge cases. A possible solution might be to create a hash for the path instead of an array. In that case, neo4j_path_to_AV (perhaps renamed to neo4j_path_to_HV) could for example return a data structure similar to this:

{
    nodes => [
        { _node => 100 },
        { _node => 101 },
    ],
    relationships => [
        { _relationship => 10, _type => 'REL', _start => 101, _end => 100 },
    ],
    type => 'path',
}

(with a possible fix for #5 not shown for simplicity)

Another possible solution would be to simply bless the arrayref returned by neo4j_path_to_AV (say, as Neo4j::Bolt::Path). That way, clients could tell lists and paths apart even when the data structures look the same.

johannessen commented 4 years ago

Should blessed paths be implemented as an alternating array, as in neo4j_value_to_SV()?

bless [$n1, $r, $n2], "Neo4j::Bolt::Path"

Or should they be a hash with two separate lists, like in SV_to_neo4j_value()?

bless { nodes => [$n1, $n2], relationships => [$r] }, "Neo4j::Bolt::Path"

Both ways are fine for me. I don’t even have a preference myself. That said, keeping it as an alternating array does seem to be less work.