Neo4j 做推薦 (5)—— 基於型別的個性化建議
如果我們知道使用者看過了哪些電影,我們可以使用此資訊來推薦類似的電影:
// Content recommendation by overlapping genres MATCH (u:User {name: "Angelica Rodriguez"})-[r:RATED]->(m:Movie), (m)-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(rec:Movie) WHERE NOT EXISTS( (u)-[:RATED]->(rec) ) WITH rec, [g.name, COUNT(*)] AS scores RETURN rec.title AS recommendation, rec.year AS year, COLLECT(scores) AS scoreComponents, REDUCE (s=0,x in COLLECT(scores) | s+x[1]) AS score ORDER BY score DESC LIMIT 10
返回結果如下:
分析:
1. 確定使用者Angelica
2. 找出使用者評過分的電影m
3. 把被評分的電影的流派找出來(g:Genre)
4. 通過流派g再返回去搜索屬於該流派的電影 (rec:Movie),並且是Angelica 沒有評過分的那部分電影
5. 返回電影,根據流派名稱數量來打分 —— [g.name, COUNT(*)] AS scores
6. 把Scores 列表中的資料列出來 —— COLLECT(scores) AS scoreComponents,
7. 從Scores 列表中,把名稱數量提取出來相加,作為得分 —— REDUCE (s=0,x in COLLECT(scores) | s+x[1]) AS score
8. 按得分高低排序
這裡運用到了幾個函式和表示式:
1. ['a', 'b', 'c'] AS list
Literal lists are declared in square brackets.
2. collect(n.property)
List from the values, ignores null
.
3. reduce(s = "", x IN list | s + x.prop)
Evaluate expression for each element in the list, accumulate the results.
備註:
[g.name, COUNT(*)] AS scores 這句話想了很久什麼意思
因為最終是要返回rec 記錄,假設我們已經找到了rec,那麼rec 記錄中的每一條,它的流派是清晰的。那麼它的流派,在 m 中出現過多少次,就是 [g.name, count(*)] 的結果。