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



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

现在我有 2 种型号 - userevent .我也有userevent之间的关系,以表示他们将参加活动。我想找出代表事件管理员的最佳方式。换句话说,我希望能够查询由用户管理的事件。

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

admin_of查询看起来很简单,但向数据库添加了另一个关系。它以后也可以处理多个管理员。

我认为后一种方式可以通过这样的东西来查询:(来自文档)EnrolledIn.where(since: 2002)所以我的搜索将包括admin: true.但是我不确定如何链接它,因为我希望它只是朋友事件。其他where查询通常将属性基于节点而不是关系。

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

更新:我想出了这样的东西

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'

这是我思考了很多的事情,本身就值得写一篇博客文章或截屏视频。我有我的最佳实践,但不会说这是最好的方法。可能有些事情我没有考虑过。不过,这是我正在使用的内容。

您确定了每种关系的巨大优点和缺点:额外的关系使遍历变得容易,添加新管理员变得容易,但维护两组本质上做同样事情的关系完全是拖累。对我来说,这甚至不是关于数据库中的额外垃圾,而是关于管理这些额外垃圾的所有额外工作。

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

  • 首先,您可以通过遵循对象的路径来获取基本的"有权访问/无访问权限",如更新中所示。如果您想将其缩小到仅朋友的事件,请执行如下操作:

    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将针对最新的节点,我们无法执行.where(rel: { score: privileged_score })。(顺便说一句,我计划尽快添加一个rel_where方法来解决这个问题。

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

我会从那里开始。当您遇到更高级的授权问题时,例如"匹配用户拥有事件或拥有事件发生的场所的事件,请包含特权信息,但多少特权信息取决于他们拥有哪些项目......如果两者兼而有之呢?"还有一些考虑因素,但我们可以下次再谈。;-)

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

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?调用将在服务器端处理,并且只返回一个布尔值,它不是非常昂贵。

我不认为这是理想的 - 它肯定效率较低 - 但它更容易构建。您始终可以重构;见鬼,你应该预料到无论如何你都需要在某个时候重构。

最新更新