iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0

[Day05] - 如何update

update可以幫助我們更新object內的propertylink

我們繼續使用[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});

以下我將以CathyJohnTomJeff來簡單稱呼其name property分別為「"Cathy"」、「"John"」、「"Tom"」與「"Jeff"」的User object

Update

假設我們現在想將Cathy加入到Johnmulti 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與內部linkobject type相同時,會有scope的問題,這時候大多需要使用detached

這裡我們update的對象是User object中,其name property為「"John"」所形成的EdgeDBSet,也就是說在set的區塊內,User將會被視為這個新EdgeDBSet,而不是原先那個含有所有User objectEdgeDBSet

也就是說,如果將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被加入到Johnmulti followers link中。

如果無法理解detached的適用時機的話,使用with會是一個不錯的query寫法。在with中,EdgeDB會自動幫您做detached,所以即使選擇的object typeupdateobject 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
};

scopesdetached是一個相當常犯的錯誤,需多加小心。

Bulk update

假設現在Cathy除了想要追蹤John外,也想追蹤JeffTom,我們可以這樣寫:

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可以依靠自己對databaseobject的熟悉程度,以較簡單的語法,來寫出針對當前情況有同等效果的query,例如:

with cathy:= (select User filter .name="Cathy")
update User filter .name not in {"John", "Cathy"}
set {
    followers+= cathy
};

上一篇
[Day04] - 如何select
下一篇
[Day06] - 如何delete
系列文
一起看無間道學EdgeDB30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言