2

User在具有双向关系的 s之间创建关系的正确方法是什么?

说我有:

class User
  include Neo4j::ActiveNode

  property :name,   type: String
  property :created_at, type: DateTime
  property :updated_at, type: DateTime

  has_many :both, :friends, model_class: 'User', type: 'connection' unique: true
  has_many :in, :followers, model_class: 'User', type: 'connection', unique: true
  has_many :out, :following, model_class: 'User', type: 'connection', unique: true
end

接着,

users = [
  User.create(name: 'Foo'),
  User.create(name: 'Bar'),
  User.create(name: 'Baz'),
]

这是合适的方法吗?这似乎非常低效:

users.each do |user|
  user.friends << users.reject { |u| u == user }
end
4

1 回答 1

2

如果您想确保user.friends返回其他两个用户,我实际上会这样做:

users.each do |user|
  other_users = users.reject { |u| u == user || user.friends.include?(u) }
  user.friends << other_users
end

现在是非常低效的!它创建一个新数组并对每个用户的数据库执行额外的查找。(FWIW,include?查找速度非常快。您也可以删除它rejectusers再次迭代以加快速度。)仍然有必要完成此操作,否则您将创建重复的关系。

在你的协会中设置unique: true只会在一个方向上拯救你。针对has_many :both关联的查询使用与方向无关的 Cypher MATCH,但CREATE操作始终需要方向,因此它们从左侧节点到右侧节点。user1.friends << user2并将user2.friends << user1在两个节点之间创建两个关系,每个方向一个。

编辑

正如您在自己对 Neo4j.rb 问题的评论中指出的那样,使用user.friends = [other_friends]将始终清除所有现有关系并防止重复。这是解决问题的一种非常酷的方法。

于 2015-04-22T02:21:10.530 回答