原文鏈接:https://markhneedham.com/blog/2018/11/05/neo4j-inferred-relationships-apoc-triggers/
對圖數(shù)據(jù)庫進(jìn)行建模時费尽,我非常看中的一點是:其在進(jìn)行關(guān)系推導(dǎo)時要比其他關(guān)系型數(shù)據(jù)庫更簡單。本文我們將學(xué)習(xí)怎樣使用APOC的觸發(fā)器特性來進(jìn)行關(guān)系推導(dǎo)的計算與保存银伟。
聚會圖模型
在開始介紹之前料饥,我們先來了解一下什么是推導(dǎo)關(guān)系梧宫。首先我們先創(chuàng)建一個小型的圖模型困食,包含有Person荆残、Meetup和Topic三類節(jié)點肋层∫隗裕可使用下面語句進(jìn)行創(chuàng)建:
MERGE (mark:Person {name: "Mark"})
MERGE (neo4jMeetup:Meetup {name: "Neo4j London Meetup"})
MERGE (bigDataMeetup:Meetup {name: "Big Data Meetup"})
MERGE (dataScienceMeetup:Meetup {name: "Data Science Meetup"})
MERGE (dataScience:Topic {name: "Data Science"})
MERGE (databases:Topic {name: "Databases"})
MERGE (neo4jMeetup)-[:HAS_TOPIC]->(dataScience)
MERGE (neo4jMeetup)-[:HAS_TOPIC]->(databases)
MERGE (bigDataMeetup)-[:HAS_TOPIC]->(dataScience)
MERGE (bigDataMeetup)-[:HAS_TOPIC]->(databases)
MERGE (dataScienceMeetup)-[:HAS_TOPIC]->(dataScience)
MERGE (dataScienceMeetup)-[:HAS_TOPIC]->(databases)
MERGE (mark)-[:MEMBER_OF]->(neo4jMeetup)
MERGE (mark)-[:MEMBER_OF]->(bigDataMeetup)
在Neo4j瀏覽器看到圖的是這樣:?
尋找潛在關(guān)系
現(xiàn)在在Person和Topic節(jié)點之間是沒有關(guān)系的,換句話說栋猖,我們不知道哪個人對哪個主題有興趣净薛。然而,我們發(fā)現(xiàn)通過Meetup節(jié)點有一個間接的關(guān)系蒲拉。?
譯者言:上圖作者畫錯了肃拜,應(yīng)該把Group換成Meetup才對。
我們假設(shè)一個人參加了多次聚會雌团,其中有3次聚會都有這個主題燃领,我們就可以推斷出他對這個主題感興趣。換句話說锦援,只要某人參加了有這主題的聚會3次或3次以上猛蔽,我們就會在Person和Topic節(jié)點間建立INTERESTED_IN關(guān)系。Cypher語句如下:
MATCH (start:Person {name: "Mark"})-[:MEMBER_OF]->()-[:HAS_TOPIC]->(topic)
WHERE not((start)-[:INTERESTED_IN]->(topic))
WITH start, topic, count(*) AS count
WHERE count >= 3
MERGE (start)-[interestedIn:INTERESTED_IN]->(topic)
SET interestedIn.tentative = true
因為Mark參加帶有任一主題的聚會都不到3次灵寺,所以曼库,上面的Cypher語句并不會創(chuàng)建INTERESTED_IN關(guān)系。我們現(xiàn)在修改一下數(shù)據(jù)略板,讓Mark再參加一次Data Science聚會毁枯,修改語句如下:
MATCH (p:Person {name: "Mark"})
MATCH (meetup:Meetup {name: "Data Science Meetup"})
MERGE (p)-[:MEMBER_OF]->(meetup)
上面語句運(yùn)行后,再執(zhí)行之前的Cypher語句叮称,此時有下面的輸出:
Created 2 relationships, completed after 2 ms.
很好后众,此時我們已經(jīng)知道Mark對DataScience和Database這兩個主題都感興趣。
我們把tentative屬性設(shè)置在true颅拦,表示這是一個推導(dǎo)關(guān)系蒂誉。后續(xù)可以考慮讓用戶確認(rèn)這個關(guān)系的正確性。
觸發(fā)器
這個關(guān)系建立起來了距帅,但是過程太痛苦了右锨。每次建立一個新的MEMBER_OF關(guān)系后,就要運(yùn)行那條推導(dǎo)關(guān)系查詢的語句碌秸,這個過程能自動化就好了绍移。
別說悄窃,還真行。使用APOC庫中的觸發(fā)器就可以讓這個過程自動化蹂窖。在APOC庫中轧抗,對觸發(fā)器是這么描述的
在觸發(fā)器中注冊一段可以被調(diào)用的Cypher查詢語句,當(dāng)Neo4j中的數(shù)據(jù)發(fā)生變化時瞬测,這段Cypher語句將會在數(shù)據(jù)的提交前或提交后被運(yùn)行起來横媚。 好,接下來我們建立一個觸發(fā)器月趟,每當(dāng)一個新關(guān)系被建立時就運(yùn)行這段腳本灯蝴。代碼如下:
CALL apoc.trigger.add("interests",
"UNWIND [rel in $createdRelationships WHERE type(rel) = 'MEMBER_OF'] AS rel
WITH startNode(rel) AS start, endNode(rel) AS end
MATCH (start)-[:MEMBER_OF]->()-[:HAS_TOPIC]->(topic)
WHERE not((start)-[:INTERESTED_IN]->(topic))
WITH start, topic, count(*) AS count
WHERE count >= 3
MERGE (start)-[interestedIn:INTERESTED_IN]->(topic)
SET interestedIn.tentative = true
",
{phase:'before'})
上面這段代碼是基于這樣一個假設(shè):在每個事務(wù)中,每個Person只會創(chuàng)建一條MEMBER_OF關(guān)系孝宗。我們的觸發(fā)器將會接收到一個事務(wù)中所有創(chuàng)建關(guān)系穷躁,然后只取出MEMBER_OF關(guān)系,接著運(yùn)行我們的Cypher語句因妇,在Person和Topic之間建立INTERESTED_IN關(guān)系问潭,表示此人對這個主題感興趣。
如果你認(rèn)為參加3次這種主題的聚會太少了婚被,想改變這個閾值狡忙,僅需要改變上面查詢語句中的這行代碼就可以:
WHERE count >= 3
好,關(guān)于APOC中的觸發(fā)器先介紹到這里摔寨,希望對你有用去枷。