在双向关系图中搜索neo4j.rb中的n级朋友

时间:2016-04-24 05:40:44

标签: graph neo4j bidirectional neo4j.rb bidirectional-relation

我有一个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创建了user1user2

然后我用以下方式搜索以下内容 user1.followings(rel_length: 2)。但结果显示为user1本身,因为user1user2都是相互追随的。

我尝试过order(:breadth_first)和其他方法来排除已经访问过的节点。我可能没有做过足够的研究,但有没有人知道如何做到这一点?

1 个答案:

答案 0 :(得分:1)

首先,您可能想要使用id_property。如果您使用property user_id并设置constraint: :unique,那么您仍会拥有自动生成的uuid媒体资源。这可能是你想要的,但只是一个抬头。这是id_property的文档:

https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Unique-IDs

对于您的问题,您的代码会生成类似于此的Cypher(我需要更改model_classrel_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')