Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在SQLite中进行高级查询以按标记搜索文件? 我在干什么?_Javascript_Sql_Database_Sqlite_Tagging - Fatal编程技术网

Javascript 如何在SQLite中进行高级查询以按标记搜索文件? 我在干什么?

Javascript 如何在SQLite中进行高级查询以按标记搜索文件? 我在干什么?,javascript,sql,database,sqlite,tagging,Javascript,Sql,Database,Sqlite,Tagging,我正在使用Electron用JavaScript编写一个文件标记程序,我想使用SQLite。不过,我不太清楚如何实现按标签搜索。我不熟悉SQL和SQLite,所以我不确定仅仅通过查询就可以做到这一点。我可以如何进行如下所述的搜索 搜索详细信息: 我已经调查了FTS3/4。从外观上看,除了通配符搜索,我可以用它做任何我想做的事情 搜索带有所有给定标记的文件:蓝天绿草 搜索没有给定标记的文件:不是蓝天也不是绿草 搜索带有某些给定标记的文件:绿色天空或蓝色天空 在标记中的任意位置搜索带有通配符的文件

我正在使用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”
  • 使用外键(必须承认,这可能需要一个不可用的功能)
在前几种情况下,您可能可以将tag_id用作inbit,这取决于键的来源(“未预料到的用户”当然会键入颜色)。这也将减少打字错误的风险

所以你可以做的是:

  • 使用“文件标签”表的联接,
    一个用于逻辑中要使用的每个标记
  • 加入文件表,以访问输出的文件名
  • 使用子查询来使用标记名而不是标记ID 或者使用更多连接,我在下面演示了这两种方法
  • 将搜索逻辑直接复制到“where”中
  • 按文件名分组,以便只获取每个文件一次
根据您的nice 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

通配符搜索可以通过像一样使用
来实现:我不确定是否使用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