使用思源数据库管理个人密码

思源笔记的数据库很适合管理以元数据为主的信息,且具有以下优势:

  • 本体存储 + 加密同步,安全有保障;
  • 视图功能可以建立一份数据的不同呈现方式,将筛选条件常驻化并快速切换;
  • 可以用关联汇总表达条目间的联系;
  • ......

我抛弃传统表格转用数据库管理密码的主要原因就是这个第三点。除去账户、账号、密码三大项,还有一类重要信息就是不同账户间的绑定关系,各种账号可能绑定到某个手机号、某个邮箱、学校认证,或者像恢复密钥一样关联特定账户;而 AdGuard 别名邮箱等既能被其他账户绑定,自身也会绑定到邮箱本体。此外还有多对多情形,例如有的账号既绑定手机号又绑定邮箱。使用简单表格虽然也不是不能处理,不过数据库还是会更方便一些。

总之在十年前用过 VB、五年前用过 Excel 后,现在我开始使用思源数据库来管理账户密码了。考虑到密码信息与常规笔记差别极大,所以将两者分笔记本放置非常合理。

忽略索引

思源具备原生的忽略索引和忽略搜索功能。参考帮助文档,前者会让被忽略的笔记完全失去存在感,只要不主动打开就不会以任何形式出现;后者则只会让被忽略的笔记不被搜索到。因此,可以专门设立一个笔记本放置隐私内容,并在 工作空间/data/.siyuan/indexignore 文件中写一行 【笔记本id】/**/* 使笔记本下的内容忽略索引。笔记本 id 可以通过在文档树打开文件位置获得。

数据库比较特殊,存储数据库的文件不在笔记本里而在 /data/storage/av 下。目前个人测试是设置文档忽略索引后,文档包含的数据库也不会被搜索到,所以暂时不需要额外处理。

在忽略索引的文档里建好数据库后就可以设置要管理的字段和筛选视图了。

字段视图

账户、账号值、密码值自然是必须要有的字段列。为了后续关联与查询,个人会将账户设为主键列,而其他属性均设为文本列。这样设置的好处是可以将账户绑定到笔记,缺点则是同一家账户的多个账号需要区分描述。考虑到目前不能简单区分同样内容的不同条目,可以直接在账户名上用 QQ邮箱(123)QQ邮箱(666) 作出区分。

除了以上三列,其余字段可以按需配置。例如,登录用的密码条目包含账号值和密码值,非登录用的密码条目如 2fa 验证码、api 密钥可以只放密码值,然后通过关联字段绑定到登录用的账户条目。想区分两种条目可以设置一个单选字段来定义登录码和功能码,或者新开一列文本字段放置非登录码。此外个人还会设立双向关联字段定义账户绑定关系,在 a 条目的关联列添加 b 条目后,就能在 b 条目的双向关联列查看绑定了 b 的条目,并用汇总字段查看各账户的绑定总数。字段列数越多能承载的信息也越多,但维护成本自然也随之增加。

数据库字段可以设立筛选条件并用视图分表固化,例如之前用单选字段来区分登录码和功能码,可以据此建立筛选得到登录表和功能表。此外根据非空关联字段可以筛选出绑定表查看所有被绑定账户。还可以新建一个空表视图用于添加新条目,将筛选条件设为某个必填字段为空,并在新建条目时最后写这一列,从而将录入与查询分离。

QV 查询

关联列会有一个额外问题就是干扰账户查询,直接用数据库搜索关键词会同时覆盖主字段和关联字段,而用筛选条件单独查某列又相对繁琐,所以个人用 Query View 插件整了一个查询面板,可以根据输入关键词一键查询主键列。某种意义上本文就是为这碟醋包的饺子。

效果演示:

听说 QV 插件后续会更新数据库查询函数,目前这个代码是参考帮助文档的 SQL 查询器结合思源 api 做的。首先要确定数据库本体 id,方法为启用集成编辑环境插件,对文档里的数据库块右键-插件-打开,其 data-av-id 对应值即为数据库本体的 id。然后在下文的 QV 查询代码里修改开头 id 值和要显示的字段名,其中第一个字段为匹配关键词的主键字段。

查询代码:

//!js // 数据库本体id const av_block_id = '20250531154713-4oewd8c'; // 目标字段名,首个字段为用于查询的主键 const col_list = [ '账户', '号值', '码值', ]; const query = async () => { let dv = Query.DataView(protyle, item, top); // useState名称符合自定义属性规则 const account_word = dv.useState('account-word', ''); const searchResult = dv.useState('search-result', []); dv.addmd(`输入账户关键词:`); const textarea = document.createElement('textarea'); textarea.className = "fn__block b3-text-field"; textarea.rows = 2; // textarea.style.fontSize = '20px'; textarea.value = account_word.value; dv.addele(textarea); const button = document.createElement('button'); button.className = "fn__block b3-button"; button.textContent = "查询"; dv.addele(button); dv.addtable(searchResult(), { fullwidth: false, cols: null, renderer: (b, a) => b[a] }); button.onclick = async () => { let av_block = await Query.request('/api/av/getAttributeView', { id: av_block_id }); const col_targets = col_list.map((name) => { return av_block.av.keyValues.filter(item => item.key.name === name)[0]; }); let account_blockID_list = await Query.request('/api/av/getAttributeViewPrimaryKeyValues', { id: av_block_id, keyword: textarea.value }); let ans; if (!('values' in account_blockID_list.rows)) { ans = []; } else { account_blockID_list = account_blockID_list.rows.values.map(item => item.blockID); ans = account_blockID_list.map(function generate_account_obj(account_blockID) { return col_targets.reduce((result, col) => { let col_value = col.values.filter(item => item.blockID === account_blockID); if (col_value.length === 0) { col_value = ''; } else { col_value = col_value[0][col.key.type].content; } result[col.key.name] = col_value; return result; }, {}); }); } account_word.value = textarea.value; searchResult(ans); dv.repaint(); }; dv.render(); } return query();

本文算是思源数据库的简单使用案例。抛开折腾因素这样的数据管理是否有意义其实不好说,姑且当成个人的小众需求,毕竟很多人连不是自己的信息都管理得井井有条津津有味。

1738072205700.png

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26049 引用 • 108131 回帖
1 操作
Imuvux 在 2025-06-01 03:45:56 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...