Bases-数据库语法

数据库语法

当用户在 Obsidian 中创建一个数据库时,它会保存为一个 .base 文件。一般来说,用户主要在可视化界面对数据库进行编辑,但用户也可以在代码块中对其进行编辑==并将其嵌入笔记==。

Bases 语法定义了视图、筛选器和公式(Formulas)。一个有效的数据库必须是符合下文所定义的模式的有效 YAML 块。

示例

下面是一个代码块形式的数据库文件的示例,每个部分的详细介绍将在下文中给出。

```base
filters:
  or:
    - file.hasTag("tag")
    - and:
        - file.hasTag("book")
        - file.hasLink("Textbook")
    - not:
        - file.hasTag("book")
        - file.inFolder("Required Reading")
formulas:
  formatted_price: 'if(price, price.toFixed(2) + " dollars")'
  ppu: "(price / age).toFixed(2)"
properties:
  status:
    displayName: Status
  formula.formatted_price:
    displayName: "Price"
  file.ext:
    displayName: Extension
summaries:
  customAverage: 'values.mean().round(3)'
views:
  - type: table
    name: "My table"
    limit: 10
    groupBy:
      property: note.age
      direction: DESC
    filters:
      and:
        - 'status != "done"'
        - or:
            - "formula.ppu > 5"
            - "price > 2.1"
    order:
      - file.name
      - file.ext
      - note.age
      - formula.ppu
      - formula.formatted_price
    summaries:
      formula.ppu: Average
```

筛选器 (Filters)

在默认情况下,数据库会囊括库中的所有文件。这里没有像 SQL 或 Dataview 中的fromsource,==用户需要依靠filters部分来定义筛选条件来缩小数据集。==

```base
filters:
  or:
    - file.hasTag("tag")
    - and:
        - file.hasTag("book")
        - file.hasLink("Textbook")
    - not:
        - file.hasTag("book")
        - file.inFolder("Required Reading")
```

有两种可以应用筛选器的情况:

  1. 在本文第一个bases代码块示例中的filters级别,这是一个全局级别,此处定义的筛选条件将被应用于该数据库中的所有视图。
  2. 在本文第一个bases代码块示例代码块中的view 级别,此处定义的筛选条件仅被应用于特定的视图。

这两个部分在功能上是等效的,当为某个视图进行评估时,它们将由一个AND连接。

filters部分既可以写成一个以字符串为形式的单一筛选语句,也可以包含一个递归定义的筛选器对象。筛选器对象可以包含andornot之一。这些键是一个由其他筛选器对象或字符串形式的筛选语句组成的异构列表。筛选语句是一行在应用于笔记时评估为真值或假值的表达式。它可以是:

  • 一则使用标准算术运算符的基本比较。
  • 一个函数。OB 内置了多种函数供用户使用,也可以用插件添加额外的函数。

筛选器和公式的语法及可用函数是相同的。

公式 (Formulas)

formulas部分定义了公式属性,这类属性可以在 base 文件中的所有视图中显示。

formulas:
  formatted_price: 'if(price, price.toFixed(2) + " dollars")'
  ppu: "(price / age).toFixed(2)"

公式属性支持基本的算术运算符和多种内置函数。未来,插件将能够添加用于公式的函数。

您可以根据属性 (Properties)的类型以不同方式引用它们:

  • 笔记属性指的是笔记的 frontmatter 中定义的属性。
    • 例:note.pricenote["price"]
    • 如果一个属性未指定前缀,则它将被视为笔记属性,==以note.为前缀==。
  • 文件属性是用于描述文件自身属性的属性,==以file.为前缀==。
    • 例:file.sizefile.ext
    • 用户也可以直接引用文件对象本身,例:file.hasLink()
  • 公式属性是数据库中的其他公式。
    • 例:formula.formatted_price
    • ==以formula.为前缀==。

一个公式可以使用来自其他公式属性所导出的值,只要不产生循环引用就行。

公式属性在 YAML 中始终以字符串形式存储,但它们实际的输出数据类型由底层数据的类型和所用函数的返回值决定。

请注意,为了在 YAML 字段中包含文本字面量,需要嵌套使用引号。文本字面量必须用单引号或双引号括起来。

属性 (Properties)

properties部分允许存储关于每个属性的配置信息。如何使用这些配置值取决于具体的视图。例如在表格布局中,displayName将被用于列标题以代表该属性

properties:
  status:
    displayName: Status
  formula.formatted_price:
    displayName: "Price"
  file.ext:
    displayName: Extension

displayName不会被用在筛选器或公式中。

译者:从“在数据库中,属性分为三种类型:”开始,到三级标题“视图”为止的文字,在英文文档中位于三级标题“函数”之后,属于二级标题“属性”,但鉴于在上文的三级标题公式 (Formulas)中已经提到公式属性,在本三级标题属性 (Properties)中也出现了一次标题,如果再把这些内容放到大下文中,属性的知识就被分成了三块,过分碎片化了,所以我将下文原来的二级标题“属性”内容移到此处,以求将属性部分的知识一次讲完而不让读者产生前后跳脱的割裂感

在数据库中,属性分为三种类型:

  1. 笔记属性存储在 Markdown 文件的 frontmatter 中。
  2. 文件属性适用于所有文件类型。
  3. 公式属性需要在.base文件中定义(见上文)。

笔记属性 (Note properties)

笔记属性仅适用于 Markdown 文件,它存储在每个笔记的 YAML frontmatter 中。这些属性可以通过note.author或其简写形式author来访问。

文件属性 (File properties)

文件属性与当前正在测试或评估的文件有关。文件属性适用于所有受支持的文件类型,包括附件。

例如,筛选器file.ext == "md"对所有 Markdown 文件为 true,其他文件则为 false

文件属性属性类型含义
file.backlinks列表反向链接文件列表。注意:此属性会消耗大量性能。如有可能,请反转查找并使用 file.links。当仓库内容发生变动时,不会自动刷新结果
file.ctime日期创建时间
file.embeds列表笔记中所有嵌入内容的列表
file.ext字符串文件扩展名
file.file文件文件对象,仅在特定函数中使用
file.folder字符串文件所在文件夹的路径
file.links列表笔记中所有内部链接的列表,包括 frontmatter 中的内部链接
file.mtime日期修改时间
file.name字符串文件名
file.path字符串文件路径
file.properties对象文件上的所有属性。注意:当仓库内容发生变动时,不会自动刷新结果。
file.size数字文件大小
file.tags列表文件正文和 frontmatter 中所有标签的列表

this.访问当前笔记文件的属性

==使用this.来访问特定文件属性,它所指向的文件取决于数据库展示的位置。==

==如果数据库在Obsidian的主面板中(非侧边栏)打开,则this.指向的是该数据库文件自身的文件属性。例如,this.file.folder将返回该数据库文件所在的文件夹路径。==

==如果数据库被嵌入到某文件中,则this.指向的是被嵌入数据库的笔记或白板文件的文件属性。例如this.file.name 将返回被嵌入数据库的笔记的名称,而非数据库的名称。==

==如果数据库在侧边栏中,this. 指向的是主面板的当前文件。这允许您基于当前文件创建上下文查询。例如file.hasLink(this.file)将返回当前文件的反向链接列表。==

视图 (Views)

views部分定义了数据的渲染方式。views列表中的每个条目都定义了相同数据的独立视图,并且可以根据需要创建任意数量的不同视图。

```base
views:
  - type: table
    name: "My table"
    limit: 10
    groupBy:
      property: note.age
      direction: DESC
    filters:
      and:
        - 'status != "done"'
        - or:
            - "formula.ppu > 5"
            - "price > 2.1"
    order:
      - file.name
      - file.ext
      - note.age
      - formula.ppu
      - formula.formatted_price
    summaries:
      formula.ppu: Average
```
  • ==type是用户从软件内置或第三方插件提供的视图类型中选择的一种,将其设定为本视图的类型。==
  • name是显示名称,可用于定义默认视图。
  • filters的定义规则同上文,但仅应用于本视图。
  • ==groupBy指定一个属性和排序方向。根据每行指定属性的值,按照排序方向,将行归入不同组别(group)。==
  • ==order规定了各属性显示的先后顺序,不能写displayName==
  • ==summaries将属性名称映射到一个特定摘要中(如上面代码中的ppu)。summaries对所有行中的属性执行聚合操作。==

视图可以添加额外的数据来存储维护状态或正确渲染所需的任何信息,但是插件作者应注意不要使用核心 Bases 插件已在使用的键。例如,表格视图可以使用limit来限制行数,或选择使用哪一列来对行进行排序及其方向。像地图这样的不同视图类型可以将其用于映射笔记中的哪个属性对应于纬度和经度,以及哪个属性应显示为固定标题。

未来,API 将允许视图读写这些值,从而允许视图构建自己的配置界面。

运算符 (Operators)

算术运算符 (Arithmetic operators)

算术运算符可对数字执行算术运算。以计算圆形周长为例radius * (2 * 3.14)

运算符含义
+
-
*
/
%
( )括号

日期算术符(Date arithmetic)

可以通过加减时长来修改日期。时长字符串有多种写法:

单位时长
y, year, years
M, month, months
d, day, days
w, week, weeks
h, hour, hours小时
m, minute, minutes分钟
s, second, seconds

要修改或偏移日期对象,请使用+-连接一个时长字符串。例如date + "1M"指的是将日期往后拨 1 个月,而date - "2h"则意味着将日期往前拨 2 小时。

全局函数today()可用于获取当前日期,now()可用于获取当前日期和时间。

  • now() + "1 day":返回从执行时间起正好 24 小时后的日期时间。
  • file.mtime > now() - "1 week":如果文件在过去一周内被修改过,则返回真值。
  • date("2024-12-01") + "1M" + "4h" + "3m":返回一个表示2025-01-01 04:03:00的日期对象。
  • 将两个日期相减以获取它们之间的毫秒差,例如now() - file.ctime
  • datetime.date():返回带时间的日期的日期部分。
  • 要格式化日期对象,请使用format()函数,例如datetime.format("YYYY-MM-DD")

比较运算符 (Comparison operators)

比较运算符可用于比较数字或日期对象。等于和不等于可用于任何类型的值,不仅限于数字和日期。在应用于其他对象时,等于和不等于在简单筛选模式下拉菜单中的选项名为”is”和“is not”。

运算符含义
==等于
!=不等于
>大于
<小于
>=大于或等于
<=小于或等于

布尔运算符 (Boolean operators)

布尔运算符可用于组合或反转逻辑值,得到true或false的结果。

运算符含义
!逻辑否
&&逻辑且
||逻辑或

函数 (Functions)

请参阅可在公式和筛选器 (Filters)中使用的函数列表。

类型 (Types)

数据库的属性值分为几种类型,公式和筛选器正是使用它来将函数应用于属性的。

字符串、数字和布尔值 (Strings, numbers, and booleans)

字符串、数字和布尔值是“原始”值,不需要借助函数来创建。

  • 字符串需要包裹在单引号或双引号之中,例:"message"
  • 数字以阿拉伯数字书写,为了清晰起见,可以选择把它们用括号括起来。例:1(2.5)
  • 布尔值写为truefalse,不带引号。

日期和时长 (Dates and durations)

日期可以表示一个特定的日期,也可以表示一个由函数指定的日期和时间,还可以表示已分配给属性的类型。

  • 要创建一个日期对象,请使用 date 函数,例:date("1917-11-07 12:00:00")
  • 要修改日期,请添加或删除一个时长,例:now() + "1 hour"today() + "7d"
  • 要比较日期,使用比较运算符(如 ><)和算术运算符(例(now() + "1d") - now() 返回86400000毫秒)
  • 要提取日期的一部分,请使用可用的字段(例:now().hour)或便捷函数(例:now.time()
  • 日期对象上还有许多其他字段和函数。

对象和列表 (Objects and lists)

  • 使用list()函数将单个元素转换为列表。这对于可能包含列表或单个值的混合属性特别有帮助。
  • 要访问列表中的元素,使用方括号[]和从 0 开始的索引。例:property[0]返回列表的第一个元素。
  • 要访问对象元素,使用方括号和元素名称或点表示法。例:property.subpropproperty["subprop"]

笔记属性中的维基链接会被自动识别为链接对象,它们将在视图中被渲染为可点击的链接。

  • 要创建一个链接,请使用全局link函数,例:link("filename")link("https://obsidian.md")
  • 用户可以从任何字符串出发创建链接,例:link(file.ctime.date().toString())
  • 要设置锚文本。,请传入一个可选的字符串或图标作为第二个参数,例:link("filename", "display")link("filename", icon("plus"))

文件对象可以通过 file.asLink() 转换为链接,并可自定义锚文本。

链接可以通过 ==!= 彼此进行比较。只要它们指向同一个文件,它们就是等效的;如果查找时文件不存在,它们的链接文本必须相同。

链接可以与文件(例: filethis)进行比较。如果链接解析为该文件,它们是等效的。例:author == this

链接也可以在列表包含检查中使用,例:authors.contains(this)

讨论

若阁下有独到的见解或新颖的想法,诚邀您在文章下方留言,与大家共同探讨。



反馈交流

其他渠道

版权声明
pkmer forum 论坛相关