Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the custom-dailynote-yyyyMMdd attribute when creating a dailynote doc #9807

Closed
frostime opened this issue Dec 3, 2023 · 19 comments
Closed
Assignees
Milestone

Comments

@frostime
Copy link
Contributor

frostime commented Dec 3, 2023

创建日记的时候为日记文档添加 custom-dailynote-yyyymmdd 属性

背景

长久以来 daily note 有一个很大的问题:无法方便的查询指定日期对应的日记,而随着插件系统日益发展,这已经越来越桎梏大家对 daily note 做一些功能优化了。

目前的查询方案非常复杂: 首先需要获取 sprig 模板,然后将模板的 now 替换成其他模板函数,再交给后端渲染获取具体的 hpath,然后再找后端查询指定 hpath 的文档。问题很明显:1) 非常麻烦 2) 一次只能查询一个 3) 性能开销大。

最近这两个版本,alt + 5 来 create daily note 的工作流发生了变化:变成了 1) 后端创建文档 2)返回文档 ID 3)前端调用接口来打开文档。由于流程的变化,现在我们可以以非常简单的方案来解决上面提到的问题:在获取到日记的 ID 后,为文档添加一个自定义的属性。

具体方案

  • 整体思路:为 yyyy-mm-dd 创建的 dailynote 增加一个自定义属性 custom-dailynote-yyyymmdd: yyyymmdd (或者和 created 等字段保持一致 yyyymmddsshhmm 也行)

  • 实现方案:在 app/src/util/mount.ts 的 fetchNewDailyNote 函数中,增加一行代码,来添加这个属性。下面是我在自己插件里实现的

    export function formatDate(date?: Date, sep=''): string {
        date = date === undefined ? new Date() : date;
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();
        return `${year}${sep}${month < 10 ? '0' + month : month}${sep}${day < 10 ? '0' + day : day}`;
    }
    
    export function setCustomDNAttr(doc_id: string, date?: Date) {
        let td= formatDate(date);
        let attr = `custom-dailynote-${td}`; //例如 custom-dailynote-20231203
        let attrs: { [key: string]: string } = {};
        attrs[attr] = td;
        serverApi.setBlockAttrs(doc_id, attrs);
    }
    
    /**
     * 打开指定的笔记本下今天的日记,如果不存在则创建
     * @param notebook_index 笔记本的 index
     */
    export async function openDiary(notebook: Notebook) {
        //...省略
        let dailynote = await serverApi.createDailyNote(notebook.id, appId);
        //...省略中间部分
        //设置日记日期的自定义属性
        setCustomDNAttr(dailynote.id);
    }

export const fetchNewDailyNote = (app: App, notebook: string) => {

只需要加这么几行代码,设置一下属性,就可以了。

好处

1. 方便查询

直接的好处就是,现在我们可以用非常统一的方式,来查询任意范围、任意时刻的 daily note 了。

image

2. 解决多对一的情况

而且,这个方案也能有效地解决日记多对一的情况。比如有的人可能把日记的模板设置为 /daily note/{{now | date "2006/01"}}。这样就导致了一整个月的日记全部放在一个文档里。

而有了上述方案,可以在单个文档中跟踪整个月的日记记录,只需要在查询的时候加一个 distinct 就可以应对多对一日记的查询。

image

image

3. 便于后面插件做进一步优化

有了这个属性,后面流式日记、自定义查询等各种优化实现起来就方便多、也会更加节省性能。

Q&A

这个提议之前提过一次,然后被 D 否决了,我这里预先回答一下可能会遇到的 battle。

#8474

Q: daily note 从设计上就是一个文档,不应该被特殊对待

这个观点本身自相矛盾,如果 daily note 应该和别的普通的文档完全一致的同等对待,那就连 alt + 5 都不应该实现。

软件内 daily note 事实上已经有特殊待遇了,在这种情况下非要坚持什么「daily note」就是一个文档,我觉得是掩耳盗铃。

退一步,就算认为添加了一个属性之后 daily note 就和别的文档地位不平等了——那又怎么样?

计算机里一个基本的哲学理念是合适的透明。如果你看不到、用不到,那就等于不存在。对于那些不会用到以后插件提供的高级功能的人来讲,多一个属性会带来什么奇怪的变化吗?他们思源的性能会因为一年多了 365 个文档属性而变得特别拉跨吗?如果不会的话——那加不加属性对他们而言就是无感的,在他们眼中日记和其他文档就是平等一致的。

Q:加了属性可能不准确的,比如用 Alt+5 创建的日记也可以重命名为其他文档。

软件的实现者不应该考虑这种问题 —— 因为这属于 exceptional 的行为。我们不能为了一小部分用户奇怪的操作就驻足不前。

Alt + 5 已经明确是「创建日记」功能了,那么创建日记后还重命名、移动文档的用户应该有「这是非正常使用方式」的自知之明。

我们真正要考虑的应该是怎么优化那些正常使用软件的用户的体验,而不是去关心那些不正常使用软件的用户的体验——错的是他们的使用方式,而不是软件

Q: 插件自己遵循这个规范,不改本体可不可以?

不可以,如果本体不遵守这个规范,那么插件规范了个寂寞。问题的核心在于,要建立一个官方认可的统一协议,以后所有的日记相关插件都遵守这个协议。

Q:加了属性之后,之前的文档怎么办?

社区开发者会解决,目前我在今日笔记里面已经了遍历过去的日记,并补充属性的功能。这些总会有办法的——前提是你要有这个属性。

image

@royc01
Copy link

royc01 commented Dec 3, 2023

支持

@muhanstudio
Copy link

支持一下,很好的想法,很棒的界面
爱来自思源😘

@winter60
Copy link

winter60 commented Dec 3, 2023

支持

1 similar comment
@zxhd863943427
Copy link
Contributor

支持

@Wetoria
Copy link

Wetoria commented Dec 3, 2023

支持。

在 logeseq 那边,由于“日记”的统一性,所以在实现日记流等功能方面是非常方便的,因为所有日记都是 yyyy-MM-dd 格式的文档。
思源则是太灵活了,缺少一个系统级的约定,以至于日记流的一些增强性的功能,不是那么好实现。

用属性的方式,对于需要的用户来说,可以实现想要的功能,对于不需要的用户来说,这也是一个不知道存在的玩意,完全没影响。

@winter60
Copy link

winter60 commented Dec 3, 2023

关系图的过滤日记目前按照日记根目录来过滤的,希望能够通过此方式来过滤 @88250

@muhanstudio
Copy link

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

@zxhd863943427
Copy link
Contributor

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不太行,假如只使用官方的创建日记功能确实如此,但我们需要想象一些比较奇妙的方向,比如我们需要创建一个过去或未来的日记。

@Wetoria
Copy link

Wetoria commented Dec 3, 2023

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不一样。比如有的人用顶栏日历这样的工具,创建了几天前的日记呢?让每一个日期,都有其对应的文档,好过一些系统级的内容。

假如用创建时间,那调整了以后,文档路径和相关内容都需要调整,但是用自定义属性只需要针对这个文档做一次调整,关联关系都会保留下来。

@frostime
Copy link
Contributor Author

frostime commented Dec 3, 2023

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不加时间戳很难应对多对一的情况。

就比如有的人,他的日记模板是 /<year>/<month>,一个月的日记全放在一个文档里。
那这时候你想要查询某一天的日记对应的文档要怎么办?

比如这种

image

文档创建于一个月1号,但是后面每天 Alt + 5 都会打开这个文档。

@muhanstudio
Copy link

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不太行,假如只使用官方的创建日记功能确实如此,但我们需要想象一些比较奇妙的方向,比如我们需要创建一个过去或未来的日记。

如果需要创建一个过去的或者未来的日记,其实也可以修改文件时间属性来达到,但是这是一个完全客制化的属性日记吗,那么两个属性分开比较好,比如一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?

@muhanstudio
Copy link

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不加时间戳很难应对多对一的情况。

就比如有的人,他的日记模板是 /<year>/<month>,一个月的日记全放在一个文档里。 那这时候你想要查询某一天的日记对应的文档要怎么办?

比如这种

image

文档创建于一个月1号,但是后面每天 Alt + 5 都会打开这个文档。

即使这样我也觉得应该是两个属性,而不是直接一个custom-dailynote-yyyymmdd,一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?以后统一调用怎么办呢,还需要正则屏蔽日期吗

@frostime
Copy link
Contributor Author

frostime commented Dec 3, 2023

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不加时间戳很难应对多对一的情况。
就比如有的人,他的日记模板是 /<year>/<month>,一个月的日记全放在一个文档里。 那这时候你想要查询某一天的日记对应的文档要怎么办?
比如这种
image
文档创建于一个月1号,但是后面每天 Alt + 5 都会打开这个文档。

即使这样我也觉得应该是两个属性,而不是直接一个custom-dailynote-yyyymmdd,一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?以后统一调用怎么办呢,还需要正则屏蔽日期吗

设置成 custom-dailynote 然后sql查询 A.name = 'custom-dailynote' 和 设置成 custom-dailynote-yyyymmdd 然后 sql 查询 A.name like 'custom-dailynote-%' 没有什么特别的区分。

更重要的是,attr name 里有时间戳,可以应对我前面提到的多对一问题;如果统一设置成 custom-dailynote,那你每天更新日记的时候这个属性就会被覆盖一遍,你要怎么区分这个文档属于那几天的日记?

我再次之前确实考虑过另一个方案 custom-dailynote: 20231201, 20231202 这样通过 append 日期的方式来存时间,后来发现这么弄还不如直接在 attrname 里存时间,实现起来还简单。

@zxhd863943427
Copy link
Contributor

如果需要创建一个过去的或者未来的日记,其实也可以修改文件时间属性来达到,但是这是一个完全客制化的属性日记吗,那么两个属性分开比较好,比如一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?

update本身会不停变动,不适合使用。

created是从id前面部分截取出来,改不了的。

即使这样我也觉得应该是两个属性,而不是直接一个custom-dailynote-yyyymmdd,一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?以后统一调用怎么办呢,还需要正则屏蔽日期吗

需要怎么样统一调用?以思源的sql查询语法来看,指定日期查询为custom-dailynote-yyyymmdd,全部查询为custom-dailynote%,获取日记日期为select value …… "custom-dailynote%",还是很自然的

@muhanstudio
Copy link

如果需要创建一个过去的或者未来的日记,其实也可以修改文件时间属性来达到,但是这是一个完全客制化的属性日记吗,那么两个属性分开比较好,比如一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?

update本身会不停变动,不适合使用。

created是从id前面部分截取出来,改不了的。

即使这样我也觉得应该是两个属性,而不是直接一个custom-dailynote-yyyymmdd,一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?以后统一调用怎么办呢,还需要正则屏蔽日期吗

需要怎么样统一调用?以思源的sql查询语法来看,指定日期查询为custom-dailynote-yyyymmdd,全部查询为custom-dailynote%,获取日记日期为select value …… "custom-dailynote%",还是很自然的

如果两个查询在现在和将来调用的区别区别并不大的话,确实一个更方便,这是一个可能涉及所有日记的更改,我也是考虑到统一性这么说,因为我不明白这是一个属性字段还是属性字段的值,我更觉得比较适合为一个统一的字段赋上不同的值

@muhanstudio
Copy link

但其实我觉得只需要增加dailynote属性,时间戳属性不需要再添加,毕竟文档本身已经有创建时间和最后修改时间的属性,想查询调出所有属性还需要用正则屏蔽后面的日期

不加时间戳很难应对多对一的情况。
就比如有的人,他的日记模板是 /<year>/<month>,一个月的日记全放在一个文档里。 那这时候你想要查询某一天的日记对应的文档要怎么办?
比如这种
image
文档创建于一个月1号,但是后面每天 Alt + 5 都会打开这个文档。

即使这样我也觉得应该是两个属性,而不是直接一个custom-dailynote-yyyymmdd,一个dailynote属性,一个是日记日期属性,这样以后联合查询会更方便,custom-dailynote-yyyymmdd使得每个日记没有了日记属性共性?以后统一调用怎么办呢,还需要正则屏蔽日期吗

设置成 custom-dailynote 然后sql查询 A.name = 'custom-dailynote' 和 设置成 custom-dailynote-yyyymmdd 然后 sql 查询 A.name like 'custom-dailynote-%' 没有什么特别的区分。

更重要的是,attr name 里有时间戳,可以应对我前面提到的多对一问题;如果统一设置成 custom-dailynote,那你每天更新日记的时候这个属性就会被覆盖一遍,你要怎么区分这个文档属于那几天的日记?

我再次之前确实考虑过另一个方案 custom-dailynote: 20231201, 20231202 这样通过 append 日期的方式来存时间,后来发现这么弄还不如直接在 attrname 里存时间,实现起来还简单。

我的意思其实是,字段应该统一,而字段值可以千变万化,直接把字段值当成字段,会不会导致数据库列太多?也可能不会?属性字段在数据库里占有单独的一列吗

@zxhd863943427
Copy link
Contributor

我的意思其实是,字段应该统一,而字段值可以千变万化,直接把字段值当成字段,会不会导致数据库列太多?也可能不会?属性字段在数据库里占有单独的一列吗

每个属性只会增加attributes表里的一行。

@88250 88250 changed the title 创建日记的时候为日记文档添加 custom-dailynote-yyyymmdd 属性 Add the custom-dailynote-yyyymmdd attribute when creating a dailynote doc Dec 3, 2023
@88250
Copy link
Member

88250 commented Dec 3, 2023

欢迎 PR。

@88250 88250 added this to the 2.11.1 milestone Dec 3, 2023
@88250 88250 changed the title Add the custom-dailynote-yyyymmdd attribute when creating a dailynote doc Add the custom-sy-dailynote-yyyymmdd attribute when creating a dailynote doc Dec 3, 2023
@88250

This comment was marked as outdated.

@88250 88250 modified the milestones: 2.11.1, backlog Dec 4, 2023
@88250 88250 self-assigned this Dec 4, 2023
@88250 88250 modified the milestones: backlog, 2.11.1 Dec 4, 2023
@88250 88250 changed the title Add the custom-sy-dailynote-yyyymmdd attribute when creating a dailynote doc Add the custom-dailynote-yyyymmdd attribute when creating a dailynote doc Dec 4, 2023
@88250 88250 changed the title Add the custom-dailynote-yyyymmdd attribute when creating a dailynote doc Add the custom-dailynote-yyyyMMdd attribute when creating a dailynote doc Dec 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants