MySQL 如何在虚拟文件夹中搜索媒体
MySQL how can I search for media in virtual folders
我正在想办法为我的媒体数据库制作一个搜索引擎。
虚拟文件夹的结构是:
table 目录
id name parent
媒体的结构是:
table 媒体
id name parent
我正在使用以下 php 函数来列出我的所有目录
function print_menu($id = 0) {
$sql = "SELECT directories.id AS id, directories.name AS name, directories.parent AS parent, directories.icon AS icon FROM directories
WHERE directories.parent = '".$id."' GROUP BY directories.id ORDER BY directories.name ASC";
$req = $cnx->prepare($sql);
$req->execute();
if ($req->rowCount()>0) {
echo "<ul>";
while ($data=$req->fetch()) {
echo "<li>".$data['name']."</li>";
print_menu($data['id']);
}
echo "</ul>";
}
}
现在假设我有以下文件夹
- 根目录
- 项目 1
- 目录 1
- 子目录 1
- 子目录 2
- 子目录 3
- 目录 2
- 子目录 1
- 目录 3
- 子目录 1
- 子目录 2
- 项目 2
- 目录 1
- 子目录 1
- 子目录 2
- 目录 2
- 子目录 1
- 子目录 2
- 子目录 3
- 目录 3
- 子目录 1
- 项目 3
- 目录 1
- 子目录 1
- 目录 2
- 子目录 1
- 目录 3
- 子目录 1
我想在 "project 1" 中搜索名为“%media_1%”的媒体,包括它的所有子文件夹,如何在不查询每个文件夹和子文件夹的情况下执行此操作?子文件夹的级别可以变化。
好的,所以我找到了一个解决方案,我正在使用上面发布的函数来获取给定目录的所有子目录的 ID,假设 "project 1" 的 ID 为 42 我将使用
$all_ids = array();
function print_menu($id = 0) {
$sql = "SELECT directories.id AS id, directories.name AS name, directories.parent AS parent, directories.icon AS icon FROM directories
WHERE directories.parent = '".$id."' GROUP BY directories.id ORDER BY directories.name ASC";
$req = $cnx->prepare($sql);
$req->execute();
if ($req->rowCount()>0) {
while ($data=$req->fetch()) {
$all_ids[] = $data['id'];
print_menu($data['id']);
}
}
}
all_ids[] = 42;
print_menu(42)
那么我只是在做一个像
这样的请求
SELECT * FROM medias WHERE medias.parent IN (".implode(',', $all_ids).") AND medias.name LIKE '%media_1%'
请求只会在"project 1"及其子目录中搜索媒体,无论有多少层
一般来说,使用 "tree" table,要获取所有后代的列表,以及已知的最大深度,您可以构造如下查询:
SELECT layerN.ID
FROM theTable AS layer1
INNER JOIN theTable AS layer2
ON layer1.id = layer2.parent_id
OR layer1.id = layer2.id
INNER JOIN theTable AS layer3
ON layer2.id = layer3.parent_id
OR layer2.id = layer3.id
...
INNER JOIN theTable AS layerN
ON `layerN-1`.id = layerN.parent_id
OR `layerN-1`.id = layerN.id
WHERE layer1.parent_id = [chosen_parent_node_id]
;
如果 ON 条件中没有额外的 "OR" 子句,则不会包括中间节点。
如果不需要中间节点,"leaf"节点深度不一,则INNER JOIN
s需要LEFT JOIN
s,SELECT
字段多一点复杂:
SELECT IFNULL(layerN.id, IFNULL(`layerN-1`.id, IFNULL(....))) AS leafID
交替
你可以有一个额外的 table 来总结总祖先,最简单的版本会有两个字段 ancestor_id
和 descendant_id
(尽管你可以包括一个 "distance" 作为出色地)。最大的问题是它需要通过某种形式的代码来维护,树上的触发器table可能是最有效和可靠的方法。
我正在想办法为我的媒体数据库制作一个搜索引擎。
虚拟文件夹的结构是:
table 目录
id name parent
媒体的结构是:
table 媒体
id name parent
我正在使用以下 php 函数来列出我的所有目录
function print_menu($id = 0) {
$sql = "SELECT directories.id AS id, directories.name AS name, directories.parent AS parent, directories.icon AS icon FROM directories
WHERE directories.parent = '".$id."' GROUP BY directories.id ORDER BY directories.name ASC";
$req = $cnx->prepare($sql);
$req->execute();
if ($req->rowCount()>0) {
echo "<ul>";
while ($data=$req->fetch()) {
echo "<li>".$data['name']."</li>";
print_menu($data['id']);
}
echo "</ul>";
}
}
现在假设我有以下文件夹
- 根目录
- 项目 1
- 目录 1
- 子目录 1
- 子目录 2
- 子目录 3
- 目录 2
- 子目录 1
- 目录 3
- 子目录 1
- 子目录 2
- 目录 1
- 项目 2
- 目录 1
- 子目录 1
- 子目录 2
- 目录 2
- 子目录 1
- 子目录 2
- 子目录 3
- 目录 3
- 子目录 1
- 目录 1
- 项目 3
- 目录 1
- 子目录 1
- 目录 2
- 子目录 1
- 目录 3
- 子目录 1
- 目录 1
- 项目 1
我想在 "project 1" 中搜索名为“%media_1%”的媒体,包括它的所有子文件夹,如何在不查询每个文件夹和子文件夹的情况下执行此操作?子文件夹的级别可以变化。
好的,所以我找到了一个解决方案,我正在使用上面发布的函数来获取给定目录的所有子目录的 ID,假设 "project 1" 的 ID 为 42 我将使用
$all_ids = array();
function print_menu($id = 0) {
$sql = "SELECT directories.id AS id, directories.name AS name, directories.parent AS parent, directories.icon AS icon FROM directories
WHERE directories.parent = '".$id."' GROUP BY directories.id ORDER BY directories.name ASC";
$req = $cnx->prepare($sql);
$req->execute();
if ($req->rowCount()>0) {
while ($data=$req->fetch()) {
$all_ids[] = $data['id'];
print_menu($data['id']);
}
}
}
all_ids[] = 42;
print_menu(42)
那么我只是在做一个像
这样的请求SELECT * FROM medias WHERE medias.parent IN (".implode(',', $all_ids).") AND medias.name LIKE '%media_1%'
请求只会在"project 1"及其子目录中搜索媒体,无论有多少层
一般来说,使用 "tree" table,要获取所有后代的列表,以及已知的最大深度,您可以构造如下查询:
SELECT layerN.ID
FROM theTable AS layer1
INNER JOIN theTable AS layer2
ON layer1.id = layer2.parent_id
OR layer1.id = layer2.id
INNER JOIN theTable AS layer3
ON layer2.id = layer3.parent_id
OR layer2.id = layer3.id
...
INNER JOIN theTable AS layerN
ON `layerN-1`.id = layerN.parent_id
OR `layerN-1`.id = layerN.id
WHERE layer1.parent_id = [chosen_parent_node_id]
;
如果 ON 条件中没有额外的 "OR" 子句,则不会包括中间节点。
如果不需要中间节点,"leaf"节点深度不一,则INNER JOIN
s需要LEFT JOIN
s,SELECT
字段多一点复杂:
SELECT IFNULL(layerN.id, IFNULL(`layerN-1`.id, IFNULL(....))) AS leafID
交替
你可以有一个额外的 table 来总结总祖先,最简单的版本会有两个字段 ancestor_id
和 descendant_id
(尽管你可以包括一个 "distance" 作为出色地)。最大的问题是它需要通过某种形式的代码来维护,树上的触发器table可能是最有效和可靠的方法。