2

User双方向の関係を持つ間の関係を作成する適切な方法は何ですか?

私が持っているとしましょう:

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

他の 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?ルックアップは非常に高速です。それを削除して、もう一度reject反復して高速化することもできます。)それでも、これを達成する必要があります。そうしないと、重複した関係が作成されます。users

あなたの協会を設定unique: trueすることは、あなたを一方向にしか救いません。アソシエーションに対するクエリhas_many :bothは、方向に依存しない Cypher を使用しますMATCHが、CREATEアクションは常に方向を必要とするため、左側のノードから右側のノードに移動します。2 つのノード間に 2 つのリレーションシップ (各方向に 1 つずつ) が作成されますuser1.friends << user2user2.friends << user1

編集

Neo4j.rb の問題へのコメントで指摘したように、を使用user.friends = [other_friends]すると、常にすべての既存の関係が消去され、重複が防止されます。それは問題を解決するための本当にクールな方法です。

于 2015-04-22T02:21:10.530 に答える