編注:我們會(huì)不定期挑選 Matrix 的優(yōu)質(zhì)文章,展示來自用戶的最真實(shí)的體驗(yàn)和觀點(diǎn)。 文章代表作者個(gè)人觀點(diǎn),少數(shù)派僅對(duì)標(biāo)題和排版略作修改。
隨著各種結(jié)合 AI 大模型的個(gè)人知識(shí)管理新工具的逐漸火熱,我們有了全新的知識(shí)交互方式,這也讓大家對(duì)傳統(tǒng)筆記軟件的知識(shí)管理方法論和 UI 創(chuàng)新上的焦慮得以舒緩,近期關(guān)于筆記軟件的討論都少了很多。但作為一個(gè)仍在堅(jiān)持人工進(jìn)行知識(shí)鏈接的「手藝人」,我依然很關(guān)心筆記軟件交互上的創(chuàng)新優(yōu)化,就像我很喜歡一篇文章里的一句話:
人腦是一種濕件,視覺和心理上看似瑣碎的提示,可能就會(huì)帶來意外的幫助。有時(shí),一點(diǎn)留白就能給思考增加深度,一段距離就能給創(chuàng)意留出空間。
所以在此我想和大家分享一個(gè)在 Notion 中的實(shí)踐小技巧(雖然實(shí)現(xiàn)難度并不?。?,希望能改善大家在使用 Notion 數(shù)據(jù)庫進(jìn)行知識(shí)管理時(shí)的交互體驗(yàn),同時(shí)也和大家一起挖掘一下 Notion 數(shù)據(jù)庫的使用潛力。
背景
在使用 Notion 數(shù)據(jù)庫的子項(xiàng)目功能時(shí),頁面之間可以進(jìn)行多層嵌套關(guān)聯(lián),從而在數(shù)據(jù)庫中呈現(xiàn)出一個(gè)樹狀的層級(jí)結(jié)構(gòu)。
一個(gè)典型的折疊嵌套數(shù)據(jù)庫
這套可以折疊的樹狀結(jié)構(gòu)非常好用,我們可以概覽所有條目,隨意在任何節(jié)點(diǎn)進(jìn)行增刪減改。但也有一些使用上的小問題,那就是「無法單拎出來一棵樹」。
截至 Notion 的最新版本(2.51),在無篩選的情況下,所有的條目會(huì)一起出現(xiàn);而在有篩選的情況下,篩選條件是針對(duì)具體節(jié)點(diǎn)生效的,我們無法對(duì)單個(gè)樹狀結(jié)構(gòu)的所有節(jié)點(diǎn)進(jìn)行篩選、提取和展示。而在模板或者數(shù)據(jù)庫頁面的選項(xiàng)卡中,只能篩選直接和當(dāng)前頁面關(guān)聯(lián)的頁面,如果樹結(jié)構(gòu)的層級(jí)數(shù)量不固定且超過了2層,那么就很難在一個(gè)篩選頁面內(nèi)完整呈現(xiàn)整個(gè)樹結(jié)構(gòu)了。也就是說,我們沒有辦法在一個(gè)數(shù)據(jù)庫視圖中只展示節(jié)點(diǎn)1及其下屬的全部層級(jí)子節(jié)點(diǎn)(包括節(jié)點(diǎn)1.1,1.1.1,1.2,1.2.1)。這使得我們無法對(duì)內(nèi)容進(jìn)行聚焦。
所以,我希望在數(shù)據(jù)庫的任意頁面,通過模板或選項(xiàng)卡的數(shù)據(jù)庫視圖可以自動(dòng)篩選出所有和當(dāng)前頁面有直接或間接的上下關(guān)系的頁面。在這個(gè)過程中要盡量做到全自動(dòng),除了構(gòu)建樹狀關(guān)系本身外,不需要我們進(jìn)行額外的操作,也不需要外部工具輔助,最終達(dá)成如下的篩選效果:
期望效果
接下來我會(huì)分步詳細(xì)講解操作方法。
實(shí)現(xiàn)思路
為了方便描述,我們借用數(shù)據(jù)結(jié)構(gòu)的術(shù)語,將所有通過上下級(jí)關(guān)系直接或間接關(guān)聯(lián)起來形成的樹狀結(jié)構(gòu)的所有頁面稱作一棵「樹」,我們?cè)?Notion 中討論的都是無環(huán)有向樹,具體含義是:
1. 有向:節(jié)點(diǎn)之間是雙向鏈接,上級(jí)關(guān)聯(lián)和下級(jí)關(guān)聯(lián)是不同屬性;
2. 無環(huán):頁面之間不能出現(xiàn)直接或間接的首尾相連;
3. 樹結(jié)構(gòu):任意節(jié)點(diǎn)的父頁面數(shù)量不能超過1個(gè)(即,入度 ≤ 1 ),樹和樹之間互不相交。
其中,第3條并不需要嚴(yán)格執(zhí)行,但這里為了簡(jiǎn)化場(chǎng)景,暫時(shí)作此規(guī)定。另外,由于 Notion 自身性能和機(jī)制的限制,樹的深度不要超過10層。
一棵樹最頂端的節(jié)點(diǎn)(入度 = 0)稱為「根節(jié)點(diǎn)」,最底端的節(jié)點(diǎn)(出度 = 0)是「葉子節(jié)點(diǎn)」;對(duì)于任意節(jié)點(diǎn) x,從根節(jié)點(diǎn)到節(jié)點(diǎn) x 的所有節(jié)點(diǎn)都是x的「祖先」(節(jié)點(diǎn) x 也是自己的祖先);對(duì)任意節(jié)點(diǎn)x,從節(jié)點(diǎn)x到葉子節(jié)點(diǎn)的所有節(jié)點(diǎn)都是x的「后代」(節(jié)點(diǎn)x也是自己的后代)。
于是,我們可以重新闡述一下目標(biāo):我們期望在任意節(jié)點(diǎn)頁面,均可以通過模板或數(shù)據(jù)庫選項(xiàng)卡的形式,自動(dòng)篩選出該頁面的所有祖先和后代節(jié)點(diǎn),從而在任意一個(gè)節(jié)點(diǎn)頁面能且只能展示該頁面所在的整個(gè)樹的結(jié)構(gòu),方便進(jìn)行單個(gè)項(xiàng)目的追蹤和編輯。
為了達(dá)成這個(gè)目標(biāo),我們需要在原有的上下關(guān)聯(lián)字段之外,通過單獨(dú)的字段記錄該節(jié)點(diǎn)的所有祖先和后代節(jié)點(diǎn)。我們?cè)谌粘J褂弥兄恍枰S護(hù)直接的上下關(guān)聯(lián)字段,而祖先記錄字段要可以自動(dòng)更新。具體方法為:先通過函數(shù)遞歸回溯所有祖先節(jié)點(diǎn),再通過自動(dòng)化將獲取到的祖先節(jié)點(diǎn)關(guān)聯(lián)到新的Relation 字段上,這樣就可以在其祖先頁面上篩選到該頁面了。
思路清晰后,我們可以開始操作了。
操作步驟0. 準(zhǔn)備好層級(jí)關(guān)聯(lián)數(shù)據(jù)庫
我們的演示數(shù)據(jù)庫包括 2 棵樹,各有 3 層的深度,關(guān)聯(lián)的屬性分別命名為「父頁面」和「子頁面」。
如果是對(duì)于已有的數(shù)據(jù)庫進(jìn)行改造的,只要保證有雙向父子關(guān)聯(lián)字段,且滿足有向無環(huán)的標(biāo)準(zhǔn)即可。
1. 添加自關(guān)聯(lián)字段,設(shè)置自動(dòng)化填充
首先要在數(shù)據(jù)庫中設(shè)置一個(gè)關(guān)聯(lián)當(dāng)前頁面的 Relation 字段。這個(gè)字段很重要,Notion 并不支持在函數(shù)中直接將當(dāng)前頁面作為 block 引用,因此我們需要通過一個(gè)關(guān)聯(lián)到自己的 Relation 字段來實(shí)現(xiàn),方便之后的函數(shù)引用和自動(dòng)化關(guān)聯(lián)。
1. 添加單向的 Relation 字段,關(guān)聯(lián)當(dāng)前數(shù)據(jù)庫,命名為 self_page,用于添加當(dāng)前頁面。
新建 2 個(gè)更新過程中用到的字段。這里是一個(gè)小技巧,如果是改造已有數(shù)據(jù)庫,當(dāng)前已經(jīng)有很多頁面了,對(duì)舊頁面一個(gè)個(gè)手動(dòng)添加關(guān)聯(lián)自身并不現(xiàn)實(shí),可以結(jié)合按鈕和自動(dòng)化功能:
2. 新建 Date 字段,命名為「刷新用 Date」,這個(gè)字段用作啟動(dòng)各種自動(dòng)化功能。
新建函數(shù)字段,命名為「是否需要更新」,函數(shù)代碼見下圖。這個(gè)字段主要是為了減少之后按鈕和自動(dòng)化的操作量,提升效率。這一步也可以不做,就是如果之后每次更新的頁面過多,自動(dòng)化和按鈕可能會(huì)罷工(頻繁被掐斷)。
// 是否需要更新 if(empty(prop("self_page")),1,0)
3. 新建 Button 字段,命名為「更新頁面」,具體功能為,點(diǎn)擊后將所有頁面需要更新的頁面(即 是否需要更新字段 > 0)的頁面的「刷新用 Date」字段設(shè)置為觸發(fā)時(shí)間,用于觸發(fā)之后的自動(dòng)化任務(wù)。
4. 創(chuàng)建自動(dòng)化流程,讓所有頁面自動(dòng)關(guān)聯(lián)自身
自動(dòng)化的觸發(fā)條件為新增頁面和編輯「刷新用 Date」字段,這樣,不論是我們新增頁面還是通過點(diǎn)擊更新按鈕更新舊頁面,所有頁面的 self_page 字段都會(huì)關(guān)聯(lián)上自身,供我們之后使用。
5. 點(diǎn)擊「更新頁面」按鈕,填充所有頁面,完成關(guān)聯(lián)。
2. 通過遞歸回溯頂層節(jié)點(diǎn)
我們首要的目標(biāo)是,在每個(gè)頁面追溯到它所有的祖先節(jié)點(diǎn),即它的父節(jié)點(diǎn),父節(jié)點(diǎn)的父節(jié)點(diǎn),父節(jié)點(diǎn)的父節(jié)點(diǎn)的父節(jié)點(diǎn)……以此類推,于是,這里要用到一點(diǎn)遞歸思維。
我們首先創(chuàng)建一個(gè) Formula 字段叫做「祖先頁面」,那么它等于:當(dāng)前頁面+父頁面的上層頁面,而它父頁面的上層頁面就包括 父頁面+父頁面的父頁面的上層頁面,形成一個(gè)長長的list,那么就可以一層一層上溯到全部的上層頁面。簡(jiǎn)單寫來就是:
prop("上溯祖先") = [prop("self_page"),prop("父頁面").map(current.prop("上溯祖先"))]
這里的map()
函數(shù)可以用來引用關(guān)聯(lián)頁面的相關(guān)屬性,具體用法就不展開了。
但由于 Notion 的設(shè)置,我們無法在一個(gè)函數(shù)中引用自己,因此我們需要一個(gè)中轉(zhuǎn)的 Formula 字段繞開限制。因此兩個(gè)字段的最終定義為:
// 上溯祖先 [prop("self_page"),prop("父頁面").map(current.prop("上溯祖先_中轉(zhuǎn)")).flat()].flat().unique() // 上溯祖先_中轉(zhuǎn) prop("上溯祖先")
其中flat()
函數(shù)是為了將嵌套的多層 List 打平為單層的 List ,unique()
函數(shù)用于去重。
這樣,我們就可以在任意一個(gè)頁面的屬性中上溯到它所有的祖先節(jié)點(diǎn)了,效果如下:
到這里,我們的目標(biāo)就完成一半了。但是,在 Notion 的數(shù)據(jù)庫篩選中,F(xiàn)ormula 字段的結(jié)果是被當(dāng)做字符串來處理的,那么我們就沒有辦法在模板或數(shù)據(jù)庫頁面選項(xiàng)卡中自動(dòng)篩選當(dāng)前頁面的相關(guān)頁面。于是,我們需要繼續(xù)把函數(shù)上溯的結(jié)果轉(zhuǎn)化為 Relation 字段。
3. 通過自動(dòng)化將上溯結(jié)果記錄為 Relation
1. 建立 Relation 屬性
首先,我們還是要新建一對(duì)關(guān)聯(lián)屬性,仍是關(guān)聯(lián)在當(dāng)前數(shù)據(jù)庫上的,命名為「祖先頁面」,對(duì)應(yīng)地,「祖先頁面」的逆向關(guān)聯(lián)就是「后代頁面」。
之后我們的操作目標(biāo)都是為了將上面的「上溯祖先」字段的內(nèi)容轉(zhuǎn)移到「祖先頁面」字段中。
2. 定義更新用函數(shù)
這里,我們先更新一下「是否需要更新」字段的定義,圈定需要更新的頁面范圍,方便之后使用:
// 是否需要更新 if(empty(prop("self_page")),1,0)+if(prop("祖先頁面").sort()!=prop("上溯祖先").sort(),1,0)
3. 設(shè)置自動(dòng)化
現(xiàn)在我們可以開始創(chuàng)建自動(dòng)化流程,為了保證任何從屬關(guān)系發(fā)生變動(dòng)時(shí)都會(huì)自動(dòng)更新相關(guān)字段,自動(dòng)化的觸發(fā)條件包括以下 3 個(gè)的任意一個(gè):
然后是自動(dòng)化的操作,我們的目標(biāo)是更新「祖先頁面」,這里要選擇 編輯屬性-祖先頁面-自定義函數(shù),函數(shù)內(nèi)填充:
4. 點(diǎn)擊更新按鈕,自動(dòng)化填充數(shù)據(jù)
第一次更新時(shí)可能要多按幾次「更新頁面」按鈕,直到所有頁面的祖先頁面字段在自動(dòng)化的作用下填充了完整的值。(這個(gè)按鈕在之后的使用中也是有用的,當(dāng)你發(fā)現(xiàn)頁面更新而相應(yīng)的字段和關(guān)聯(lián)并沒有及時(shí)更新時(shí),你可以手動(dòng)點(diǎn)擊按鈕來更新整個(gè)數(shù)據(jù)庫的頁面)。
于是,我們建立完成了上溯祖先頁面的自動(dòng)化流程建設(shè)。
4. 可視化:在數(shù)據(jù)庫選項(xiàng)卡中展示樹結(jié)構(gòu)通過 Rollup 關(guān)聯(lián)樹結(jié)構(gòu)中所有節(jié)點(diǎn)
由于一棵樹內(nèi)所有節(jié)點(diǎn)的祖先節(jié)點(diǎn)都包括根節(jié)點(diǎn),因此任意頁面的所有祖先頁面的全部后代頁面也就包括了整個(gè)樹內(nèi)的全部節(jié)點(diǎn),這樣我們就真正達(dá)成了「樹內(nèi)任意一節(jié)點(diǎn)關(guān)聯(lián)到樹內(nèi)全部節(jié)點(diǎn)」的目標(biāo)。
創(chuàng)建一個(gè) Rollup (匯總)字段,命名為「樹全部節(jié)點(diǎn)」,設(shè)置如下:
使用選項(xiàng)卡展示樹結(jié)構(gòu)
將頁面布局改為選項(xiàng)卡式,并添加一個(gè)數(shù)據(jù)庫卡片,展示的選項(xiàng)可以隨便選一個(gè)(之后還要改篩選條件),命名為「項(xiàng)目樹」。
Rollup 字段是無法直接進(jìn)行篩選的,但是可以在高級(jí)篩選中使用,因此要在篩選里設(shè)置「合并到高級(jí)篩選中」:
最后,我們?cè)賹⒆禹?xiàng)目的展示方式設(shè)置為「嵌套在折疊中」,就得到我們最終目標(biāo)的展示內(nèi)容了:
最終效果
現(xiàn)在,我們就可以在任意一個(gè)節(jié)點(diǎn)頁面內(nèi)展示其所在項(xiàng)目樹的全部節(jié)點(diǎn)啦,并且該視圖內(nèi)仍可以直接對(duì)各個(gè)節(jié)點(diǎn)及其下屬節(jié)點(diǎn)進(jìn)行增刪改減,并沒有任何限制。
我們共用了 8 個(gè)字段、2 個(gè)自動(dòng)化流程和 1 個(gè)按鈕,搭建起這套全自動(dòng)的全鏈接工作流,這個(gè)方法可以說比較完美地解決了我在最開始提出的需求,并且完全沒有超出 Notion 自身的體系,不涉及任何外部工具資源,因此一次配置完就可以在任何終端上安全使用。
當(dāng)然還是存在一些問題的,主要是:
功能受官方限制:在這個(gè)過程中用到了很多擦邊的手法,如遞歸函數(shù)、將非法的函數(shù)結(jié)果賦值給 Relation 字段等,這些都是官方不鼓勵(lì)(甚至明確做了限制)的操作,導(dǎo)致在制作時(shí)會(huì)時(shí)不時(shí)出現(xiàn)一些難以解釋的報(bào)錯(cuò),解決方法也都是想辦法繞過限制,這就導(dǎo)致有一些潛在的失效風(fēng)險(xiǎn)。
性能表現(xiàn)比較差:流程涉及到的函數(shù)計(jì)算比較復(fù)雜,對(duì)自動(dòng)化依賴嚴(yán)重,導(dǎo)致實(shí)際計(jì)算較慢,而且自動(dòng)化的更新不一定及時(shí),偶爾需要手動(dòng)點(diǎn)擊刷新按鈕;選項(xiàng)卡的篩選規(guī)則復(fù)雜,展示也比較慢,而且隨著數(shù)據(jù)庫內(nèi)頁面數(shù)量增多,會(huì)愈加緩慢。(不過就我個(gè)人使用經(jīng)驗(yàn)來講,目前有幾千個(gè)頁面的數(shù)據(jù)庫還是撐得住的)。
上述問題已經(jīng)超出我的解決范圍了,也只能期待有一天官方可以大發(fā)慈悲直接將這個(gè)做成正式的功能,大家也不用這么費(fèi)勁了。
P.S.
不知你還記不記得我在前面說過,「樹與樹之間不交叉」這個(gè)條件不是必須的,那么如果是有交叉的樹會(huì)有什么效果呢?可以看我自己的一個(gè)案例:由于我的樹狀知識(shí)庫之間會(huì)相互交叉引用,這使得當(dāng)我打開任意一個(gè)知識(shí)卡片后,所有和當(dāng)前樹有間接關(guān)聯(lián)(引用過同一個(gè)知識(shí)卡片)的知識(shí)樹都會(huì)同時(shí)展示出來,不僅易于探索和編輯,還不容易迷路,讓我時(shí)刻清楚我當(dāng)前所在的位置。這雖然比不上雙鏈筆記軟件里的關(guān)系星圖,但在使用效果上也很接近了。
如果你有其他更好的實(shí)踐方法和思路,歡迎和我交流。
https://sspai.com/post/101372?utm_source=wechat&utm_medium=social
作者:清垚土土土
責(zé)編:廣陵止息
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.