使用 max() 和 min() 同时保留项目
max()
和 min()
的聚合函数非常有用,但有时您会发现自己在与 Cypher 的聚合行为作斗争,因为某些情况下应该很简单。
这通常发生在您想要计算 max()
或 min()
或其他内容,但要保留与该最大值或最小值关联的项目或项目时。
让我们使用一个非常简单的示例,一个在商店购买食物的人员图。
(:Person {name})-[:BOUGHT]->(:FoodItem {name})
我们想要找到,每个人的,他们购买最多的食物项目或项目。
应该很简单却很复杂
我们可以轻松地使用 max()
找到他们购买最多的食物项目的计数。
MATCH (person:Person)-[:BOUGHT]->(food:FoodItem)
WITH person, food, count(food) as timesBought
RETURN person, max(timesBought) as mostBoughtCount
但我们丢失了与生成该结果的食物关联的数据!哪些食物项目被购买了那么多次?它只是一个食物项目,还是几个项目之间有联系?
如果我们像这样将 food
保持在范围内:RETURN person, food, max(timesBought) as mostBoughtCount
,我们将得到错误的结果,因为每个食物都在它自己的行上列出,而 mostBoughtCount
是针对每个食物的,而不是在所有食物中汇总的。
如果我们像这样收集 food
:RETURN person, collect(food) as foods, max(timesBought) as mostBoughtCount
,虽然 mostBoughtCount
是正确的,但我们收集了所有食物,而且不知道哪个与该最大值相关联。
我们被迫放弃这种方法,而是执行排序、收集,然后保留最上面的结果。
MATCH (person:Person)-[:BOUGHT]->(food:FoodItem)
WITH person, food, count(food) as timesBought
ORDER BY timesBought DESC
RETURN person, collect(food)[0] as favoriteFood, max(timesBought) as mostBoughtCount
但是,再次,平局怎么办?一个人可能有多种他们最喜欢的食物在他们的 mostBoughtCount 中并列。我们可能会花费大量时间重构该查询,执行 collect() 和 UNWIND,计数和比较,并且该查询变得更加复杂。
APOC 过程有助于保持事情简单
首先,我们获得了自定义过程,然后我们获得了自定义函数,最后我们获得了编写自定义聚合函数的能力。从 APOC 3.5.0.5 开始,添加了新的函数来帮助解决这些情况。
|
返回一个映射 {items:[], value:n},其中 |
还有一个类似工作的 apoc.agg.minItems()
。
简而言之,此函数让我们使用相当于 min() 或 max(),但也能保留与该值关联的项目或项目。
如果我们将其添加到我们的查询中,我们将得到
MATCH (person:Person)-[:BOUGHT]->(food:FoodItem)
WITH person, food, count(food) as timesBought
WITH person, apoc.agg.maxItems(food, timesBought) as maxData
RETURN person, maxData.items as favoriteFoods, maxData.value as mostBoughtCount
这让我们可以保留所有并列为最喜欢的食物,如果我们想限制并列,我们可以将其作为函数调用中的一个额外参数添加。
此页面有帮助吗?