如何使用 PostgreSQL 按路径过滤

lr_*_*tim 3 python sql postgresql ltree sqlmodel

我的数据库中有一些资源继承到它们的子资源。当我查询资源时,我还需要能够获取继承的资源。我有一个名为path我计划使用的字段。始终path包含与我们当前正在处理的资源相关的所有资源的完整路径。

例子:

+-----------------------------------------+
| id | res_id    | path                   |
|-----------------------------------------|
| 1  | res_1     | res_1                  |
| 2  | res_1.1   | res_1.res_1.1          |
| 3  | res_1.2   | res_1.res_1.2          |
| 4  | res_1.1.1 | res_1.res_1.1.res_1.1.1|
+-----------------------------------------+
Run Code Online (Sandbox Code Playgroud)

如果我查询res_1.1,我还必须获取 ,res_1因为它是 的父级res_1.1。如果我得到res_1.1.1,我还必须得到第 1 行和第 2 行,因为它们包含在 的路径中res_1.1.1。希望得到一些关于如何使用 Postgres 执行此操作的建议。如果这是重要信息,我也用来sqlmodel编写查询。

编辑。对于含糊的介绍,我深表歉意,该参数path已经是sqlalchemy Ltree字段。我希望这能让事情变得更简单一些?

Erw*_*ter 5

使用类型ltree

\n

事实证明您正在使用附加模块ltree。点 ( .) 是明确的分隔符。假设path是类型ltree(您还没有澄清)可以简化任务。有专门的操作员,例如:

\n
\n

ltree @> ltree\xe2\x86\x92boolean

\n

左参数是右参数的祖先(或等于)吗?

\n
\n

所以:

\n
SELECT t.*\nFROM   tbl_ltree t1   \nJOIN   tbl_ltree t ON t.path @> t1.path\nWHERE  t1.res_id = \'res_1_1_1\';  -- your search term here\n
Run Code Online (Sandbox Code Playgroud)\n

ltree还提供了 GiST 索引的运算符类:

\n
CREATE INDEX tbl_ltree_path_gist_idx ON tbl USING GIST (path);\n
Run Code Online (Sandbox Code Playgroud)\n

..可以被上面的查询使用。另外,您还会在 上拥有另一个 B 树索引res_id

\n

res_id是完全多余的,可以忽略甚至丢弃。我们可以使用另一个 ltree 运算符path来代替:

\n
\n

ltree ~ lquery\xe2\x86\x92boolean

\n

ltree 与 lquery 匹配吗?

\n
\n

关于lquery类型。

\n
CREATE INDEX tbl_ltree_path_gist_idx ON tbl USING GIST (path);\n
Run Code Online (Sandbox Code Playgroud)\n

db<>在这里摆弄

\n

只需要 GiST 索引。

\n

使用类型text

\n

在使用text而不是ltree(您还没有澄清)时,这是多种方法之一:

\n
SELECT *\nFROM   tbl_ltree   \nWHERE  path @> (SELECT path FROM tbl_ltree WHERE path ~ \'*.res_1_1_1\'::lquery);\n
Run Code Online (Sandbox Code Playgroud)\n

db<>在这里摆弄

\n

子查询t1分为path其构建块。然后加入到另一个实例tbl_txt

\n