这是一个非常好的问题!我还没有完整的解决方案,但有一些想法:正如Martin Preusse所说,我们希望生成笛卡尔产品。
这是困难的,但是你可以通过大量的黑客攻击,包括使用的变通办法,双减少:
WITH [['a', 'b'], [1, 2, 3], [true, false]] AS hs
WITH hs, size(hs) AS numberOfHobbys, reduce(acc = 1, h in hs | acc * size(h)) AS numberOfCombinations, extract(h IN hs | length(h)) AS hLengths
WITH hs, hLengths, numberOfHobbys, range(0, numberOfCombinations-1) AS combinationIndexes
UNWIND combinationIndexes AS combinationIndex
WITH
combinationIndex,
reduce(acc = [], i in range(0, numberOfHobbys-1) |
acc + toInt(combinationIndex/(reduce(acc2 = 1, j in range(0, i-1) | acc2 * hLengths[j]))) % hLengths[i]
) AS indices,
reduce(acc = [], i in range(0, numberOfHobbys-1) |
acc + reduce(acc2 = 1, j in range(0, i-1) | acc2 * hLengths[j])
) AS multipliers,
reduce(acc = [], i in range(0, numberOfHobbys-1) |
acc + hs[i][
toInt(combinationIndex/(reduce(acc2 = 1, j in range(0, i-1) | acc2 * hLengths[j]))) % hLengths[i]
]
) AS combinations
RETURN combinationIndex, indices, multipliers, combinations
的想法是这样的:我们乘潜力值的数量,例如对于['a', 'b'], [1, 2, 3], [true, false]
,我们计算n = 2×3×2 = 12
,使用查询中的第一个reduce
。然后,我们从0到n-1进行迭代,并使用公式a×1 + b×2 + c×6
为每个数字分配一行,其中a,b,c指示各自的值,因此全部为非负整数,并且a < 2
,b < 3
和c < 2
。
0×1 + 0×2 + 0×6 = 0
1×1 + 0×2 + 0×6 = 1
0×1 + 1×2 + 0×6 = 2
1×1 + 1×2 + 0×6 = 3
0×1 + 2×2 + 0×6 = 4
1×1 + 2×2 + 0×6 = 5
0×1 + 0×2 + 1×6 = 6
1×1 + 0×2 + 1×6 = 7
0×1 + 1×2 + 1×6 = 8
1×1 + 1×2 + 1×6 = 9
0×1 + 2×2 + 1×6 = 10
1×1 + 2×2 + 1×6 = 11
结果是:
╒════════════════╤═════════╤═══════════╤═════════════╕
│combinationIndex│indices │multipliers│combinations │
╞════════════════╪═════════╪═══════════╪═════════════╡
│0 │[0, 0, 0]│[1, 2, 6] │[a, 1, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│1 │[1, 0, 0]│[1, 2, 6] │[b, 1, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│2 │[0, 1, 0]│[1, 2, 6] │[a, 2, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│3 │[1, 1, 0]│[1, 2, 6] │[b, 2, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│4 │[0, 2, 0]│[1, 2, 6] │[a, 3, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│5 │[1, 2, 0]│[1, 2, 6] │[b, 3, true] │
├────────────────┼─────────┼───────────┼─────────────┤
│6 │[0, 0, 1]│[1, 2, 6] │[a, 1, false]│
├────────────────┼─────────┼───────────┼─────────────┤
│7 │[1, 0, 1]│[1, 2, 6] │[b, 1, false]│
├────────────────┼─────────┼───────────┼─────────────┤
│8 │[0, 1, 1]│[1, 2, 6] │[a, 2, false]│
├────────────────┼─────────┼───────────┼─────────────┤
│9 │[1, 1, 1]│[1, 2, 6] │[b, 2, false]│
├────────────────┼─────────┼───────────┼─────────────┤
│10 │[0, 2, 1]│[1, 2, 6] │[a, 3, false]│
├────────────────┼─────────┼───────────┼─────────────┤
│11 │[1, 2, 1]│[1, 2, 6] │[b, 3, false]│
└────────────────┴─────────┴───────────┴─────────────┘
因此,对于您的问题,查询可能是这样的:
MATCH (p:Person)-[:likes]->(h:Hobby)-[:canDoAt]->(pl:Place)
WITH p, h, collect(pl.name) AS places
WITH p, collect(places) AS hs
WITH hs, size(hs) AS numberOfHobbys, reduce(acc = 1, h in hs | acc * size(h)) AS numberOfCombinations, extract(h IN hs | length(h)) AS hLengths
WITH hs, hLengths, numberOfHobbys, range(0, numberOfCombinations-1) AS combinationIndexes
UNWIND combinationIndexes AS combinationIndex
WITH
reduce(acc = [], i in range(0, numberOfHobbys-1) |
acc + hs[i][
toInt(combinationIndex/(reduce(acc2 = 1, j in range(0, i-1) | acc2 * hLengths[j]))) % hLengths[i]
]
) AS combinations
RETURN combinations
这看起来是这样的:
╒════════════════════════════════════╕
│combinations │
╞════════════════════════════════════╡
│[Diner, Lounge, Lake] │
├────────────────────────────────────┤
│[Daves BarGrill, Lounge, Lake] │
├────────────────────────────────────┤
│[Diner, Dive Bar, Lake] │
├────────────────────────────────────┤
│[Daves BarGrill, Dive Bar, Lake] │
├────────────────────────────────────┤
│[Diner, Lounge, Mountain] │
├────────────────────────────────────┤
│[Daves BarGrill, Lounge, Mountain] │
├────────────────────────────────────┤
│[Diner, Dive Bar, Mountain] │
├────────────────────────────────────┤
│[Daves BarGrill, Dive Bar, Mountain]│
└────────────────────────────────────┘
很显然,我们也想得到这个人n和他/她的爱好的名字:
MATCH (p:Person)-[:likes]->(h:Hobby)-[:canDoAt]->(pl:Place)
WITH p, h, collect([h.name, pl.name]) AS places
WITH p, collect(places) AS hs
WITH p, hs, size(hs) AS numberOfHobbys, reduce(acc = 1, h in hs | acc * size(h)) AS numberOfCombinations, extract(h IN hs | length(h)) AS hLengths
WITH p, hs, hLengths, numberOfHobbys, range(0, numberOfCombinations-1) AS combinationIndexes
UNWIND combinationIndexes AS combinationIndex
WITH
p, reduce(acc = [], i in range(0, numberOfHobbys-1) |
acc + [hs[i][
toInt(combinationIndex/(reduce(acc2 = 1, j in range(0, i-1) | acc2 * hLengths[j]))) % hLengths[i]
]]
) AS combinations
RETURN p, combinations
结果:
╒═══════════╤════════════════════════════════════════════════════════════╕
│p │combinations │
╞═══════════╪════════════════════════════════════════════════════════════╡
│{name: Joe}│[[eat, Diner], [drink, Lounge], [hike, Lake]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Daves BarGrill], [drink, Lounge], [hike, Lake]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Diner], [drink, Dive Bar], [hike, Lake]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Daves BarGrill], [drink, Dive Bar], [hike, Lake]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Diner], [drink, Lounge], [hike, Mountain]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Daves BarGrill], [drink, Lounge], [hike, Mountain]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Diner], [drink, Dive Bar], [hike, Mountain]] │
├───────────┼────────────────────────────────────────────────────────────┤
│{name: Joe}│[[eat, Daves BarGrill], [drink, Dive Bar], [hike, Mountain]]│
└───────────┴────────────────────────────────────────────────────────────┘
我可能是这个得太多,所以任何意见是值得欢迎的。
一个重要的评论:这与纯Cypher如此复杂的事实可能是一个很好的迹象,你最好从客户端应用程序计算。
接受为出色想出解决方案!是的,编写一个简单的查询可能会更有意义,该查询列出了人员,hobby,列表(地点),并在cilent应用程序中执行其他操作。 – Azeli
您正在反思这一点,但它仍然非常令人印象深刻;) –