我有一个User类定义如下
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
我已经分别使用user_id 1和2创建了user1
和user2
。
然后我用以下方式搜索以下内容
user1.followings(rel_length: 2)
。但结果显示为user1
本身,因为user1
和user2
都是相互追随的。
我尝试过order(:breadth_first)
和其他方法来排除已经访问过的节点。我可能没有做过足够的研究,但有没有人知道如何做到这一点?
答案 0 :(得分:1)
首先,您可能想要使用id_property
。如果您使用property
user_id
并设置constraint: :unique
,那么您仍会拥有自动生成的uuid
媒体资源。这可能是你想要的,但只是一个抬头。这是id_property
的文档:
https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Unique-IDs
对于您的问题,您的代码会生成类似于此的Cypher(我需要更改model_class
和rel_class
选项):
MATCH user15573
WHERE (ID(user15573) = {ID_user15573})
MATCH user15573-[rel1:`FOLLOWS`*2]->(result_followings:`User`)
在Cypher的单个MATCH
子句中,Neo4j将确保在单个路径遍历中不会遍历相同的关系。但正如你所说,如果他们互相追随,这意味着它可以跟随其他关系回到原始用户。在这种情况下,您可以将原始用户从潜在结果中排除:
MATCH user15573
WHERE (ID(user15573) = {ID_user15573})
MATCH user15573-[rel1:`FOLLOWS`*2]->(result_followings:`User`)
WHERE result_followings <> user15573
在Ruby中,这将是:
user1.as(:source).followings(:target, nil, rel_length: 2).where('source <> target')