這是一個非常好的問題!我還沒有完整的解決方案,但有一些想法:正如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
您正在反思這一點,但它仍然非常令人印象深刻;) –