摘要:在語義網等圖模型中,遵循開放世界假設,對於數據中未包含的事實,都認為是未知的而非假的。
本文分享自華為雲社區《圖數據庫對 NULL 屬性值支持情況》,原文作者:你好_TT 。
NULL(空值)是數據庫中對數據屬性未知或缺失的一種標識,用於指示數據庫中不存在的數據值。當圖數據庫中圖數據的某個節點或邊的屬性值缺失或未定義時,該屬性值即為NULL。
那么為什么圖數據庫需要支持NULL值呢?
在語義網等圖模型中,遵循開放世界假設,對於數據中未包含的事實,都認為是未知的而非假的。例如對於一個包含若干學生的圖數據庫,有如下兩條查詢:
- 查詢一:找出大學在清華大學的人
- 查詢二:找出大學不在清華大學的人
如果圖數據庫中的小明同學沒有填寫學校,那么小明是屬於查詢一的結果集,還是屬於查詢二的結果集。開放世界假設認為,未包含的數據是未知的而非虛假,在這個邏輯的支撐下,小明既不屬於查詢一的答案,也不屬於查詢二的答案。
圖數據庫,通過NULL值實現這一邏輯。
下面我們來看看各圖數據庫對NULL 屬性值的支持情況。
GDB
對於字符串這種數據類型,支持長度為零的空字符串,表示為:””,不使用雙引號的空白域表示不存在,為 nullptr。
NebulaGraph
默認情況下,插入點或邊時,屬性值可以為 NULL ,用戶也可以設置屬性值不允許為 NULL (NOT NULL),即插入點或邊時必須設置該屬性的值,除非創建屬性時已經設置默認值。
HugeGraph
可以指定一些字符串代表空值,比如"NULL",如果該列對應的頂點/邊屬性又是一個可空屬性,那在構造頂點/邊時不會設置該屬性的值。
Amazon Neptune
允許輸入空白字段,一個空白字段被認為是一個NULL值。
Neo4j
在Cypher中,NULL用於表示缺失或者未定義的值。從概念上講,NULL意味着缺失的未知的值,它的處理方式與其他值的處理方式略有不同。
Gremlin
TinkerGraph可以配置為支持NULL作為屬性值,但並不是所有的圖數據庫產品都支持。所以在使用之前請務必檢查supportsNullPropertyValues()的功能或查看說明文檔。
TigerGraph
不支持NULL和NOT NULL 屬性。圖數據庫中不支持NULL這個值。如果在創建頂點或邊實例時未為屬性賦值,則以該數據類型的默認值為該屬性賦值,最新版本已經廢除這條。
華為雲圖引擎服務GES
支持NULL屬性值。當輸入空白字段時,認為該屬性值為NULL。
下面舉例說明,假設導入數據的schema為:
<label name="movie"> <properties> <property name="ChineseName" cardinality="single" dataType="string"/> <property name="Year" cardinality="single" dataType="int"/> </properties> </label> <label name="user"> <properties> <property name="Gender" cardinality="single" dataType="enum" typeNameCount="2" typeName1="F" typeName2="M"/> <property name="School" cardinality="single" dataType="string"/> <property name="Age" cardinality="single" dataType="int"/> </properties> </label> <label name="rate"> <properties> <property name="Datetime" cardinality="single" dataType="date"/> <property name="Score" cardinality="single" dataType="double" /> </properties> </label>
導入的點數據為:
張三,user,M,清華大學 李四,user,,北京大學,20 小明,user,,,21 Titanic,movie,泰塔尼克號,1997
導入的邊數據為:
張三,Titanic,rate,,4
調用GES原生API接口進行邊查詢:
GET http://{SERVER_URL}/ges/v1.0/{project_id}/graphs/{graph_name}/edges/detail? source=張三&target=Titanic
得到結果:
"edges": [ { "index": "0", "source": "張三", "label": "rate", "properties": { "Score": [ 4.0 ], "Datetime": [ null ] }, "target": "Titanic" } ]
可以看到,查詢到的邊的 Datetime 的屬性值是 null , 這是因為該屬性字段輸入時是空白字段。
另外,GES 支持 Gremlin 和 Cypher 兩種主流的圖查詢語言,下面我們通過 Cypher 驗證文章開始時提出的問題。
分別進行以下三個查詢:
match (n:user) where n.School='清華大學' return n match (n:user) where n.School<>'清華大學' return n match (n:user) where n.School is null return n
得到的查詢結果分別為:
"row": [ { "School": "清華大學", "Gender": "M", "Age": null } ], "meta": [ { "id": "張三", "type": "node", "labels": [ "user" ] } ] "row": [ { "School": "北京大學", "Gender": null, "Age": 20 } ], "meta": [ { "id": "李四", "type": "node", "labels": [ "user" ] } ] "row": [ { "School": null, "Gender": null, "Age": 21 } ], "meta": [ { "id": "小明", "type": "node", "labels": [ "user" ] } ]
當 n.School 為 null 時,n.School<>'清華大學' 和 n.School='清華大學' 的返回值都是非 true,所以小明未在前兩個查詢的結果集中。這背后是GES Cypher支持的三值運算邏輯,這套邏輯支撐起了文章開始時所述的查詢,也遵循了語義網等模型的開放世界假設。