update可以幫助我們更新object內的property及link。
我們繼續使用[Day03]中定義的schema:
type User {
required name: str;
multi followers: User;
}
type Article {
required title: str;
required author: User;
}
執行下列query建立兩個Article object及四個User object。
insert Article {
title:= "first article",
author:= (insert User {name:= "John"})
};
insert Article {
title:= "second article",
author:= (insert User {name:= "Jeff"})
};
for name in {"Tom", "Cathy"}
union (insert User {name:= name});
以下我將以Cathy、John、Tom與Jeff來簡單稱呼其name property分別為「"Cathy"」、「"John"」、「"Tom"」與「"Jeff"」的User object。
假設我們現在想將Cathy加入到John的multi followers link中,可以這麼寫:
update User filter .name="John"
set {
followers+= (select detached User filter .name="Cathy")
};
我們可以使用+=將所選取的EdgeDBSet加入multi followers link,並使用-=將所選取的EdgeDBSet移出multi followers link。
這裡需注意當所選取的object type與內部link的object type相同時,會有scope的問題,這時候大多需要使用detached。
這裡我們update的對象是User object中,其name property為「"John"」所形成的EdgeDBSet,也就是說在set的區塊內,User將會被視為這個新EdgeDBSet,而不是原先那個含有所有User object的EdgeDBSet。
也就是說,如果將query寫為下面這樣:
update User filter .name="John"
set {
followers+= (select User filter .name="Cathy")
};
其multi followers link將不會改變,因為(select User filter .name="Cathy")是一個空的EdgeDBSet。
這點可以透過下面query來確認:
select User{**} filter .name="John";
{
default::User {
id: 67fd98c6-3f5b-11ef-9acb-ff0f4fd955f6,
name: 'John',
followers: {}
}
}
這裡可以看出,沒有任何User object被加入到John的multi followers link中。
如果無法理解detached的適用時機的話,使用with會是一個不錯的query寫法。在with中,EdgeDB會自動幫您做detached,所以即使選擇的object type與update的object type一樣,也不需要擔心。
所以原先query可以改寫成:
with cathy:= (select User filter .name="Cathy")
update User filter .name="John"
set {
followers+= cathy
};
或是:
with john:= (select User filter .name="John"),
cathy:= (select User filter .name="Cathy")
update john
set {
followers+= cathy
};
scopes與detached是一個相當常犯的錯誤,需多加小心。
假設現在Cathy除了想要追蹤John外,也想追蹤Jeff跟Tom,我們可以這樣寫:
with names:= {"Jeff", "Tom"},
cathy:= (select User filter .name="Cathy")
for name in names
union (
update User filter .name=name
set {
followers+= cathy
}
);
或是省略union:
with names:= {"Jeff", "Tom"},
cathy:= (select User filter .name="Cathy")
for name in names
update User filter .name=name
set {
followers+= cathy
};
當然,編寫EdgeQL可以依靠自己對database內object的熟悉程度,以較簡單的語法,來寫出針對當前情況有同等效果的query,例如:
with cathy:= (select User filter .name="Cathy")
update User filter .name not in {"John", "Cathy"}
set {
followers+= cathy
};