neo4jrb / activegraph

An active model wrapper for the Neo4j Graph Database for Ruby.
http://neo4jrb.io
MIT License
1.39k stars 276 forks source link

creates_unique on ActiveGraph::Relationship deletes to_node's :out relationship, too? #1660

Closed bobmazanec closed 2 years ago

bobmazanec commented 2 years ago

Summary

ActiveGraph::Relationship with creates_unique (both :none and :all) removes existing similar relationship out of new relationship's to_node

Example

Given

# models/is_response_to.rb
class IsResponseTo
  include ActiveGraph::Relationship

  from_class :Post
  to_class   :Post
  type       :IS_RESPONSE_TO

  creates_unique :none
end

# models/post.rb
class Post 
  include ActiveGraph::Node
  [...]
  has_one  :out, :stimulus,  rel_class: :IsResponseTo
  has_many :in,  :responses, rel_class: :IsResponseTo
end

image

When

I try to create (new:Post)-[:IS_RESPONSE_TO]->(<Node 27>) (without affecting <Node 27>'s existing existing relationship to <Node 26>)

[...]
ActiveGraph::Base.transaction do
  response = Post.create stimulus: @post, [...]
  [...]
end

respond_to do |format|
  if @reacted_to.save
    [...]

Then

in the log, I see post4 created as response in the controller code, then this surprising/suspicious part

 Post#stimulus
  MATCH(post27)
  WHERE(ID(post27) = $ID_post27)
  MATCH(post27)-[r:`IS_RESPONSE_TO`]->(n:`Post`)
  DELETE r | {:ID_post27=>27}
 BOLT:0ms

and this expected stuff

 Post#stimulus
  MATCH(post4)
  WHERE(ID(post4) = $ID_post4)
  MATCH(post4)-[r:`IS_RESPONSE_TO`]->(n:`Post`)
  DELETE r | {:ID_post4=>4}
BOLT: 24ms

CYPHER 
 MATCH 
   (from_node), 
   (to_node)
 WHERE 
   (ID(from_node) = $from_node_id) AND 
   (ID(to_node) = $to_node_id)
 MERGE (from_node)-[rel:`IS_RESPONSE_TO` {}]->(to_node)
 SET rel.`created_at` = $setter_rel_created_at
 RETURN rel | {:from_node_id=>4, :to_node_id=>27, :setter_rel_created_at=>1629570639}

Expected

creates (<node 4>)-[:IS_RESPONSE_TO]->(<node 27>)

Actual

image

Runtime information:

Neo4j database version: 4.0-community (Kernel version: 4.0.12,68ff600fbd22e8e07882ead9ed2e4987450006cb) via Docker neo4j:4.0-community activegraph gem version: 10.1.0 rails 6.1.0 ruby 3.0.1

Additional

This worked as expected in a prior project with neo4j 9.6.2 / neo4j-core 9.0.0. Given I'm creating (<node 4>)-[:IS_RESPONSE_TO]->(<node 27>), I'm surprised to see

[...]
MATCH(post27)-[r:`IS_RESPONSE_TO`]->(n:`Post`)
DELETE r | {:ID_post27=>27}

which deletes <node 27>'s outbound [:IS_RESPONSE_TO]

Working in the 10 branch, I'm planning to see if I can repro by adding some new examples to spec/e2e/relationship_spec.rb.

Posting here to see if I've missed anything "obvious" while I get the Vagrant and/or Docker env setup (hints/pointers/lessons-learned welcome on that part, too).

To the contributors: thanks for the gem! To all: thanks in advance for any response/info

bobmazanec commented 2 years ago

Dup of #1650