Neo4j gem – 处理管理关系的首选方法

这主要是一个设计/效率问题,但我想看看是否有一种首选方法来处理neo4j,而不是我在sql db中如何处理它。

现在我有2个模型 – userevent 。 我还有userevent之间的关系来表示他们将参加活动。 我想找出代表活动管理员的最佳方式。 换句话说,我希望能够查询用户所关注的事件。

一种方法是在用户和event之间创建一个名为admin_of的新关系。 另一种方法是创建参与关系的管理属性。 admin: true

admin_of查询看起来很简单,但又增加了与db的关系。 它也可以在以后处理多个管理员。

后一种方式可以通过类似的东西来查询:(来自文档) EnrolledIn.where(since: 2002)所以我的搜索将包括admin: true 。 但是我不知道如何链接这个,因为我希望它只是朋友活动。 另一个查询通常基于节点而不是关系的属性。

后一种方法似乎是一种首选的方法,但查询它的正确方法是什么? 或者是第一种更简单的方法,即使它增加了额外的关系?

更新:我想出了类似的东西

result = Event.query_as(:event).match("event<-[invite: INVITED]-(user: User)<-[:FRIENDS_WITH]-(user)").where(invite: {admin: /true/}).pluck(:event)

基于详细的查询

https://github.com/neo4jrb/neo4j/wiki/Search-and-Match

更新2

我现在有这个,但没有得到匹配。 什么是开始解决我的查询错误的最佳方法?

current_user.friends.events.query_as(:event).match("event<-[invite]-(user: User)<-[friends_with]-(user)").where(invite: {admin: true}, event: {detail: 'property'}).pluck(:event)

我的用户模型有

has_many :both, :events, model_class: 'Event', rel_class: 'Invite'

我的活动模型有

has_many :both, :users, model_class: 'User', rel_class: 'Invite'

我的邀请模特有

  from_class Event to_class User type 'invited' 

这是我想到的很多东西,值得一篇博文或截屏。 我有我最好的做法,但不会说这是最好的做法。 可能有一些我没有考虑过的事情。 不过,这是我正在使用的内容。

你确定了每个人的优点和缺点:额外的关系使遍历变得容易,并且添加新的管理员很容易,但保持两组基本上做同样事情的关系是完全拖累。 对我来说,它甚至不是关于数据库中的额外废话,而是关于管理额外垃圾的所有额外工作。

一般来说,当我可以利用现有的rel时,我会尽量避免为管理信息之类的内容创建额外的关系。 我已经确定了两种做法:

  • 首先,您可以通过跟踪对象的路径获得基本的“有访问/无访问权限”,如更新中所示。 如果你想把它缩小到只有朋友的事件,做这样的事情:

    friend.events.query_as(:event).match.all_the_rest_of_your_chain

通过为朋友开始,您将只返回与他们相关的事件。 现在,如果你只想要他们拥有的活动……

  • 您可以在关系中使用整数属性(我通常称为我的score来表示该用户对其的访问级别。 整数很酷,因为你可以设置一个评分约定,0是没有权限,50是编辑,99是管理员 – 类似的东西 – 然后说“where rel.score> {admin_score}”你只会得到那些他们具有正确访问级别或更高级别的关系。 那就像……

    friend.events(:e, :rel).where("rel.score > {privileged_score}").params(privileged_score: 0).continue_your_chain

请注意,我们必须使用字符串并设置我们自己的参数,因为在QueryProxy中将以最近的节点为目标,我们不能这样做.where(rel: { score: privileged_score }) 。 (我打算尽快添加一个rel_where方法来处理这个问题,BTW。)

无论如何,这只会返回朋友的事件,他们的访问级别大于默认值,这意味着某种高级安全级别。

我从那里开始。 当您进入更高级的授权问题时,例如“匹配用户拥有事件或拥有事件发生地点的事件”,包括特权信息,但有多少特权信息取决于他们拥有哪些项目……以及怎么样呢?“ 还有一些考虑因素,但我们可以再谈一次。 😉

您可能还想阅读https://github.com/neo4jrb/neo4j/wiki/Search-and-Scope上的范围。 在当前版本中它有点粗糙和错误,但Brian有一个开放的公关更新,使其更好。 您将能够编写自定义方法:

 def privileged_events(score = 0 events(:e, :rel).where("rel.score = {rel_score}").params(rel_score: score) end 

然后执行类似user.privileged_events.more_query_chain_methods以使查询更可重用。 我们有一个要修复的规范,它只是一个双重问题,它将被合并到master中。 我们应该在几天内找到4.0候选版本(如果我们甚至认为RC是必要的)。

还有一件事…

还需要考虑的是,您还可以执行两个查询以仅返回特权信息:返回用户应该看到的所有事件,然后根据视图中的关系进行过滤。

 <%= @events.each do |event| %> <% if @event.users(:u, :rel).where("rel.score = {admin_score}").params(admin_score: 99).include?(current_user) %> # do stuff <% end %> <% end %> 

include? 调用将在服务器端处理,只返回一个布尔值,它不是非常昂贵。

我不认为它是理想的 – 它的效率肯定不高 – 但它的构建要容易得多。 你总能重构; 地狱,你应该期待你无论如何都需要重构。