Javascript 如何在SQLite中进行高级查询以按标记搜索文件? 我在干什么?
我正在使用Electron用JavaScript编写一个文件标记程序,我想使用SQLite。不过,我不太清楚如何实现按标签搜索。我不熟悉SQL和SQLite,所以我不确定仅仅通过查询就可以做到这一点。我可以如何进行如下所述的搜索 搜索详细信息: 我已经调查了FTS3/4。从外观上看,除了通配符搜索,我可以用它做任何我想做的事情Javascript 如何在SQLite中进行高级查询以按标记搜索文件? 我在干什么?,javascript,sql,database,sqlite,tagging,Javascript,Sql,Database,Sqlite,Tagging,我正在使用Electron用JavaScript编写一个文件标记程序,我想使用SQLite。不过,我不太清楚如何实现按标签搜索。我不熟悉SQL和SQLite,所以我不确定仅仅通过查询就可以做到这一点。我可以如何进行如下所述的搜索 搜索详细信息: 我已经调查了FTS3/4。从外观上看,除了通配符搜索,我可以用它做任何我想做的事情 搜索带有所有给定标记的文件:蓝天绿草 搜索没有给定标记的文件:不是蓝天也不是绿草 搜索带有某些给定标记的文件:绿色天空或蓝色天空 在标记中的任意位置搜索带有通配符的文件
- 搜索带有所有给定标记的文件:
蓝天绿草
- 搜索没有给定标记的文件:
不是蓝天也不是绿草
- 搜索带有某些给定标记的文件:
绿色天空或蓝色天空
- 在标记中的任意位置搜索带有通配符的文件:
*sky和*grass和*bl*e*
- 以上的组合:
/蓝天和绿色*
绿草和蓝天或绿天
CREATE TABLE files (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE tags (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE file_tags (
id INTEGER PRIMARY KEY,
file_id INTEGER,
tag_id INTEGER
);
示例:
查询:蓝天绿草
结果:
文件1
查询:蓝天或蓝天
结果:
文件1、文件2、文件4
查询:蓝天绿草或蓝草
结果:
文件1、文件2
查询:*ish*
结果:
文件_3
查询:*bl*e*
结果:
文件1、文件2、文件3、文件4
查询:*天空而不是蓝草
结果:
文件1,文件3
注意:如果SQLite不是适合这项工作的工具,我愿意接受建议。在我看来,通过修改数据库结构,您可以更轻松地完成这项工作。
例如
- 一致使用“文件id”和“标签id”
而不是在这两种情况下有时使用“id” - 使用外键(必须承认,这可能需要一个不可用的功能)
- 使用“文件标签”表的联接,
一个用于逻辑中要使用的每个标记 - 加入文件表,以访问输出的文件名
- 使用子查询来使用标记名而不是标记ID 或者使用更多连接,我在下面演示了这两种方法
- 将搜索逻辑直接复制到“where”中
- 按文件名分组,以便只获取每个文件一次
select fs.name from file_tags t1
inner join file_tags t2 on t1.file_id = t2.file_id
inner join files fs on fs.id = t1.file_id
where t1.tag_id = (select id from tags where name = 'blue_sky')
and t2.tag_id = (select id from tags where name = 'green_grass')
group by fs.name;
select fs.name from file_tags t1
inner join file_tags t2 on t1.file_id = t2.file_id
inner join files fs on fs.id = t1.file_id
where t1.tag_id = (select id from tags where name = 'blue_sky')
or t2.tag_id = (select id from tags where name = 'green_sky')
group by fs.name;
-- note, here I had to derive from your desired output
-- that you want a '()' around the 'or'
select fs.name from file_tags t1
inner join file_tags t2 on t1.file_id = t2.file_id
inner join file_tags t3 on t1.file_id = t3.file_id
inner join files fs on fs.id = t1.file_id
where t1.tag_id = (select id from tags where name = 'blue_sky')
and (t2.tag_id = (select id from tags where name = 'green_grass')
or t3.tag_id = (select id from tags where name = 'blue_grass')
)
group by fs.name;
select fs.name from file_tags t1
inner join files fs on fs.id = t1.file_id
inner join tags ts on ts.id = t1.tag_id
where ts.name like '%ish%'
group by fs.name;
select fs.name from file_tags t1
inner join files fs on fs.id = t1.file_id
inner join tags ts on ts.id = t1.tag_id
where ts.name like '%bl%e%'
group by fs.name;
select fs.name from file_tags t1
inner join files fs on fs.id = t1.file_id
inner join tags ts on ts.id = t1.tag_id
where ts.name like '%sky' and not ts.name = 'blue_grass'
group by fs.name;
select name from file_tags t1
inner join files fs on t1.file_id = fs.id
where (select name from tags where id = t1.tag_id) like "%sky"
and not file_id in
(select file_id from file_tags
where tag_id = (select id from tags where name = 'blue_grass')
);
输出:
name
----------
file_1.png
name
----------
file_1.png
file_2.png
file_4.png
name
----------
file_1.png
file_2.png
name
----------
file_3.png
name
----------
file_1.png
file_2.png
file_3.png
file_4.png
name
----------
file_1.png
如果我补充:
INSERT INTO tags (name) VALUES ('greenish_blue_sky');
INSERT INTO file_tags (file_id, tag_id) VALUES(file3_id, greenish_blue_sky_id);
最后一个输出部分是:
name
----------
file_1.png
file_3.png
使用SQLite 3.18.0通配符搜索可以通过像一样使用
来实现:我不确定是否使用SQLite,因为我不使用它。您的数据库设计看起来不错。它将使您能够实现您的既定目标。我认为吸引注意力的是您使用javascript的意图。它在客户端上运行。数据库通常位于服务器上。也许电子解决了这个问题。我不知道它是什么,所以我不能说。@juzraai我试过像
这样的,但我不知道如何使用它来构造一个满足我其余条件的查询。@DanBracuk Electron允许你用HTML、CSS和Javascript编写桌面应用程序。我正在编写一个普通的桌面应用程序,使用一个简单的数据库来存储我需要的信息。编辑:任何对Electron感兴趣的人的链接您能否在非常有用的创建…
行中添加几行插入…
?还请根据该数据库内容,为给定的所需搜索示例提供所需结果。我的答案比删除文件扩展名的编辑内容稍旧(尽管发布时间较晚)。它不会更改查询代码。谢谢,这是一个非常好的答案。乍一看,这正是我需要的东西。我将不得不花一些时间来处理这些查询,以便详细理解它们。不过有一件事。在上一个示例中,我期望文件1和3,而不是1、2和4。看起来您的查询应该会产生我期望的输出。我不明白为什么没有。我没有注意到(说不出为什么)。原因是这两个检查都是在任何标记的每个标记上同时进行的,而不是在组合上。要同时查看这两个文件,需要两次连接file_标记。我将在稍后(大约6小时后)修复。我“修复”了它。正如我所解释的,我的查询是错误的,但是您只得到带有附加标记的file1和file3,并且在file3上额外使用它。否则,greenish\u blue\u sky\u id
未定义。我用了greenish\u blue\u grass\u id
来制作我的MCVE,“not”这个词很难理解。您需要一个没有blue grass标记的文件列表,而不是错误地使用至少有一个标记不同于blue grass的文件创建列表。有趣。
name
----------
file_1.png
file_3.png