2

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

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

一种方法是admin_of在 user 和event. 另一种方法是创建参与关系的管理属性。就像是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'
4

1 回答 1

2

这是我想了很多的事情,并且本身就值得发表一篇博文或截屏。我有我的最佳实践,但不会说这是最好的方法。可能有一些我没有考虑过的事情。不过,这就是我正在使用的东西。

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

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

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

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

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

  • 您可以在关系中使用整数属性(我通常称为 mine 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

请注意,我们必须使用字符串并设置我们自己的参数,因为where在 QueryProxy 中将针对最近的节点,我们不能这样做.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让查询片段更可重用。我们有一个规范要修复,它只是一个双精度的问题,它将被合并到主控中。我们应该在几天内发布 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?调用将在服务器端处理并仅返回一个布尔值,它并不是非常昂贵。

我不认为它是理想的——它肯定效率较低——但它更容易构建。你总是可以重构;地狱,您应该期望无论如何您都需要重构。

于 2014-11-25T23:43:03.730 回答