1. 程式人生 > >Neo4j 做推薦 (5)—— 基於型別的個性化建議

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(*)] 的結果。