在[Day03]~[Day06],我們將使用下面這個schema幫助我們熟悉EdgeDB的基本操作。
type User {
required name: str;
multi followers: User;
}
type Article {
required title: str;
required author: User;
}
這個schema內定義了:
User object type
property
,且為required
及 single
,即每次insert
時都要提供一個str
型態。link
,且為optional
及multi
,即每次insert
時不一定要提供;但如果有提供的話,可以包含一個以上的User object
。Article object type
property
,且為required
及single
,即每次insert
時都要提供一個str
型態。link
,且為required
及single
,即每次insert
時都要提供一個User object
。insert可以幫助我們建立object
。在EdgeDB中關鍵字是case insensitive,所以insert
與InSeRt
會被視為是相同的。在傳統SQL中,很多人都習慣將關鍵字大寫,但在EdgeQL
的官方文件中,關鍵字皆以小寫呈現。我自己是習慣寫成小寫,但大家可以依照自己的喜好來選擇,我相信只要寫法是一致的,閱讀起來應該都不會太困難。
以下我將以Cathy
、John
、Tom
與Jeff
來簡單稱呼其name property
分別為「"Cathy"」、「"John"」、「"Tom"」與「"Jeff"」的User object
。
假設我們想建立John
,可以使用insert
搭配shape(即{}
)來做:
insert User {name:= "John"};
這邊有兩點需要注意:
property
或link
時需使用:=
。;
作為結束。接著我們建立一個Article object
,其title property
為「"first article"」,author link
為John
:
insert Article {
title:= "first article",
author:= assert_single(User)
};
目前我們只有John
一個User object
,所以我們可以「取巧」以User
代替,而不必真的選取到John
。由於author
是single link
,所以必須使用assert_single()來確定其返回結果不會多於一個(如果沒有使用assert_single()
或返回結果多於一個的話,都會報錯)。assert_single()
是一個funtion
,可以說是EdgeDB最常使用的保護措施之一,剛開始可能會覺得不太習慣,但這就像是另類的型別檢查一樣,雖然一開始要多花點功夫,但卻可以避免後面可能生的一連串錯誤。
由於像上述這樣的情況相當常見,我們一般會使用下面這種query:
insert Article {
title:= "first article",
author:= (insert User {name:= "John"})
};
由於insert
的返回結果必定是一個或以下,所以這邊可以不用加上assert_single()
。但如果改寫為下面這樣,也是正確的寫法:
insert Article {
title:= "first article",
author:= assert_single((insert User {name:= "John"}))
};
請注意assert_single()
內需要使用括號,不可省略。如果寫成下面這樣:
❌
insert Article {
title:= "first article",
author:= assert_single(insert User {name:= "John"})
};
EdgeDB會報錯:
error: EdgeQLSyntaxError: Missing parentheses around statement used as an expression
Bulk inserts
是使用for-loop來同時生成大量的object
。例如,我們想同時生成Jeff
、Tom
及Cathy
的話,可以這麼寫:
for name in {"Jeff", "Tom", "Cathy"}
union (insert User {name:= name});
其中union為EdgeDB連接兩個EdgeDBSet
的運算子。
值得一提的是,在EdgeDBv5之後,union
變成可省略的關鍵字,也就是說上述query也可以寫成:
for name in {"Jeff", "Tom", "Cathy"}
insert User {name:= name};
如果將union
寫出來,可以更加表現出所有的query結果都是EdgeDBSet
;但是省略union
的確可以讓語法更簡潔,也更像一般程式中的for-loop
,大家可以自己選擇喜歡的寫法。