使用cypher获取最佳结果

时间:2013-08-21 10:49:43

标签: neo4j cypher

我有一个图表,其状态在时间上彼此跟随。每个状态都可以执行许多操作(0..n)和一些软件分配的一些建议(0..n)。

我可以像这样对cypher进行查询

start n=node:name(name="State")
match a<-[:hasAction]-s-[:isA]->n
s-[l?:hasRecommendation]->r 
where l.likelihood>0.2
return distinct s.name as state, collect(a.name) as actions,
r.name as recommendation, l.likelihood as likelihood
order by s.name asc, l.likelihood desc

给了我一张这样的表

state   | actions    | recommendation | likelihood
--------------------------------------------------
State 1 | [a1,a2,a3] | a1             | 0.25
State 1 | [a1,a2,a3] | a4             | 0.05
State 2 | [a2,a3]    | a3             | 0.56
State 2 | [a2,a3]    | a2             | 0.34
State 2 | [a2,a3]    | a1             | 0.15

如果我手动处理该表,我可以过滤这些结果,例如每个州只有前两个结果。这是耗时且非常不优雅的。

我的问题是,我从来不知道一个州有多少推荐,所以我不能在这里使用限制/跳过。理想情况下,我希望它只返回一定数量的状态(例如100),包括它们的最高建议 - 这个查询可以在0到100 * n行之间返回。

在密码中有没有更好的方法来实现这一目标?

1 个答案:

答案 0 :(得分:0)

实现此目的的简单方法是选择具有建议的状态并将结果限制为100,然后通过动态计算每个状态的百分位数来检索这100个状态的前2个建议,如下所示,

start n=node:name(name="State")
Match s-[:isA]->n, s-[?:hasRecommendation]->r
With distinct s
Order by s.name
limit 100
Match s-[?:hasRecommendation]->r
With s, (count(r)-1.0) / count(r) as p
Match s-[l?:hasRecommendation]->r
With s, percentile_disc(l.likelihood, p) as m
start n=node:name(name="State")
match a<-[:hasAction]-s-[:isA]->n,
s-[l?:hasRecommendation]->r 
where l.likelihood>= m
return distinct s.name as state, collect(a.name) as actions,
r.name as recommendation, l.likelihood as likelihood
order by s.name asc, l.likelihood desc

它有点冗长,但Cypher不支持嵌套函数进行聚合。所以我必须通过两个单独的查询得到“计数”和“百分位数”。