我正在使用Electron在JavaScript中编写文件标记程序,我想使用SQLite。不过,我无法弄清楚我是如何通过标签实现搜索的。我是SQL和SQLite的新手,所以我不确定这是否只能通过查询实现。我如何进行如下所述的搜索?
我已经研究过FTS3 / 4。从外观上看,除了通配符搜索外,我可以做任何我想要的事情。
blue_sky AND green_grass
NOT blue_sky AND NOT green_grass
green_sky OR blue_sky
*sky AND *grass AND *bl*e*
blue_sky AND green*
/ green_grass AND blue_sky OR green_sky
可能会改变
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
);
INSERT INTO files (name) VALUES ('file_1.png');
INSERT INTO files (name) VALUES ('file_2.png');
INSERT INTO files (name) VALUES ('file_3.png');
INSERT INTO files (name) VALUES ('file_4.png');
INSERT INTO tags (name) VALUES ('blue_sky');
INSERT INTO tags (name) VALUES ('green_sky');
INSERT INTO tags (name) VALUES ('green_grass');
INSERT INTO tags (name) VALUES ('blue_grass');
INSERT INTO tags (name) VALUES ('greenish_blue_sky');
INSERT INTO file_tags (file_id, tag_id) VALUES(file1_id, blue_sky_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file1_id, green_grass_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file2_id, blue_sky_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file2_id, blue_grass_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file3_id, greenish_blue_sky_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file4_id, green_sky_id);
INSERT INTO file_tags (file_id, tag_id) VALUES(file4_id, blue_grass_id);
查询:blue_sky and green_grass
结果:file_1
查询:blue_sky or green_sky
结果:file_1, file_2, file_4
查询:blue_sky and green_grass or blue_grass
结果:file_1, file_2
查询:*ish*
结果:file_3
查询:*bl*e*
结果:file_1, file_2, file_3, file_4
查询:*sky and not blue_grass
结果:file_1, file3
注意:如果SQLite不是正确的工作工具,我可以接受建议。
答案 0 :(得分:2)
在我看来,通过修改数据库结构,您可以更轻松地实现这一目标 E.g。
您可以在前几种情况下使用tag_ids作为inpit,具体取决于密钥的来源(“无意识的用户”当然会键入颜色)。这也可以减少拼写错误的风险。
所以你能做的是:
根据您的好MCVE,以下是您的示例查询的提案:
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