Reputation: 111
I have a User class defined as below
class User
include Neo4j::ActiveNode
include Neo4j::Timestamps
property :user_id, type: Integer, constraint: :unique
property :max_friends_count, type: Integer, default: 5
validates :user_id, :presence => true
has_many :out, :followings, model_class: :GraphUser, rel_class: :GraphRel, unique: true
has_many :in, :followers, model_class: :GraphUser, rel_class: :GraphRel, unique: true
end
I have created user1
and user2
with user_id 1 and 2 respectively.
And then I dis search followings of followings using
user1.followings(rel_length: 2)
. But the result come out as user1
itself because both user1
and user2
are following each other.
I have tried order(:breadth_first)
and other methods to exclude the nodes that have already been visited. I might not have done enough research but does anyone have any idea how to do this?
Upvotes: 1
Views: 85
Reputation: 10856
Firstly, you might want to use the id_property
. If you use a property
for user_id
and set constraint: :unique
you'll still have the automatically generated uuid
property. That may be what you want, but just a heads up. Here's the documentation for id_property
:
https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Unique-IDs
To your question, your code generates Cypher similar to this (I needed to change the model_class
and rel_class
options):
MATCH user15573
WHERE (ID(user15573) = {ID_user15573})
MATCH user15573-[rel1:`FOLLOWS`*2]->(result_followings:`User`)
In a single MATCH
clause in Cypher, Neo4j will make sure that the same relationship isn't traversed more than once for a single path traversal. But as you said if they are following each other that means that it can follow the other relationship to go back to the original user. In that can you'd need to exclude the original user from the potential results:
MATCH user15573
WHERE (ID(user15573) = {ID_user15573})
MATCH user15573-[rel1:`FOLLOWS`*2]->(result_followings:`User`)
WHERE result_followings <> user15573
In Ruby this would be:
user1.as(:source).followings(:target, nil, rel_length: 2).where('source <> target')
Upvotes: 1