Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.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/0/search/2.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
带标记的MySQL全文布尔搜索_Mysql_Search_Full Text Search_Tags - Fatal编程技术网

带标记的MySQL全文布尔搜索

带标记的MySQL全文布尔搜索,mysql,search,full-text-search,tags,Mysql,Search,Full Text Search,Tags,我以前从未从MYSQL进行过搜索,但我需要实现一个搜索。我有三个表:articles,articles\u tags,和tags 表articles包含我想搜索的第一个内容,即title字段 表articles\u tags是一个数据透视表,它将articles和tags关联在一起articles\u tags有两个字段,分别是:articles\u id和tag\u id 而且,表tags包含我想搜索的第二个内容,即name字段 我的问题是,我需要一种方法来搜索title字段以及与该文章相关的

我以前从未从MYSQL进行过搜索,但我需要实现一个搜索。我有三个表:
articles
articles\u tags
,和
tags

articles
包含我想搜索的第一个内容,即
title
字段

articles\u tags
是一个数据透视表,它将
articles
tags
关联在一起
articles\u tags
有两个字段,分别是:
articles\u id
tag\u id

而且,表
tags
包含我想搜索的第二个内容,即
name
字段

我的问题是,我需要一种方法来搜索
title
字段以及与该文章相关的每个标记(
tags.name
),并返回特定文章的相关性(或按相关性排序)

实现这一点的好方法是什么?我很确定不能只从一个查询中完成,所以两个查询,然后将相关性混合在一起就可以了

谢谢


编辑:忘了说,如果我能给匹配标签比匹配标题中的单词赋予更多权重,那就太棒了。我不是真的要求任何人写这篇文章,而是给我一些指导。我对PHP和MySQL都有点生疏。

有趣的是,这是关于我在两天内看到的几乎相同问题的第三个问题,请查看以下两篇帖子:,

这个快速演示查询远未优化,但应该是一个很好的起点

SELECT * FROM
(SELECT a.id, a.title, 
  MATCH (a.title) AGAINST ('$s_search_term') AS title_score,
  SUM(MATCH (t.name) AGAINST ('$s_search_term')
) AS tag_score
FROM articles AS a
LEFT JOIN articles_tags AS at
  ON a.id = at.article_id
LEFT JOIN tags AS t
  ON t.id = at.tag_id
WHERE MATCH (a.title) AGAINST ('$s_search_term') 
  OR MATCH (t.name) AGAINST ('$s_search_term')
GROUP BY a.id) AS table1
ORDER BY 2*tag_score + title_score DESC

您可能希望通过将tag_分数除以计数(t.id)来规范化它。抱歉,提供查询比解释如何进行查询更容易

从@james.c.funk给出的答案开始,但做一些更改

SELECT a.id, a.title, 
  MATCH (a.title) AGAINST (?) AS relevance
FROM articles AS a
LEFT OUTER JOIN (articles_tags AS at
  JOIN tags AS t ON (t.id = at.tag_id AND t.name = ?))
  ON (a.id = at.article_id)
WHERE MATCH (a.title) AGAINST (? IN BOOLEAN MODE) 
ORDER BY IF(t.name IS NOT NULL, 1.0, relevance) DESC;
我假设您希望标记匹配与完整字符串匹配,而不是使用全文搜索

还使用一个左外部联接而不是两个,因为如果满足对
articles\u tags
的联接,那么肯定有一个标记。将标记名比较放在联接条件中,而不是放在
WHERE
子句中


布尔模式使
MATCH()
在匹配时返回1.0,这使得它无法作为相关性度量。因此,在选择列表中进行额外的比较,以计算相关性。该值介于0.0和1.0之间。现在,我们可以通过将标记匹配排序视为具有1.0的相关性来进行更高的排序。

您可能希望了解sphinx,

以下是我在过去是如何做到这一点的。它看起来慢,但我想你会发现它不是

我增加了一点复杂性,以显示还有什么可以轻松完成。在本例中,一篇文章的部分标题匹配得1分,部分标记匹配得2分,精确标记匹配得3分,精确标题匹配得4分。然后,它将这些数据相加,并按分数排序

SELECT
  a.*,
  SUM(
    CASE WHEN a.title LIKE '%keyword%' THEN 1 ELSE 0 END
    +
    CASE WHEN t.name LIKE '%keyword%' THEN 2 ELSE 0 END
    +
    CASE WHEN t.name = 'keyword' THEN 3 ELSE 0 END
    +
    CASE WHEN a.title = 'keyword' THEN 4 ELSE END
  ) AS score
FROM article a, articles_tags at, tags t
WHERE a.id = at.article_id
AND at.tag_id=t.id
AND (a.title LIKE '%keyword%' OR t.name LIKE '%keyword%')
GROUP BY a.id
ORDER BY score;

注意:这将不会返回没有标签的文章。我使用简单的连接来减少查询中的噪音,并突出显示正在进行评分的内容。要包含不带标记的文章,只需将联接设为左联接

在这个时候,建议您将搜索任务转移到一些实际上是为这个目的而编写的东西上,这是否值得呢

在我们的产品中,我们使用MySQL存储数据,但使用Lucene(通过Solr)索引所有数据,但这并不重要

值得一看,因为它的设置相对简单,功能非常强大,而且比试图操纵数据库来做你想做的事情容易得多


很抱歉,这不是问题的直接答案,我只是觉得在这种情况下,这种事情总是值得一提:)

我看了这两个问题,但看不出它们与我的问题有什么关系。更有趣的是,这实际上是一个评论,而不是答案。嗨,比尔。我在一些地方读到,使用全文连接是不好的,因为它会迫使MySQL运行完整的表扫描,并失去宝贵的性能。“我现在要对此进行测试,看看我读到的是不是真的。@狗仔队,这取决于首先访问哪个表。MySQL使用嵌套循环算法进行连接,因此,如果您使用全文限制第一个表中匹配的行数,然后使用它查找连接表中的行,那么应该没有问题。但是如果您先扫描另一个表,然后在连接条件中使用全文,或者更糟糕的是,在全文搜索中使用第一个表的一列作为要搜索的模式(我不知道这是否可行),那么这将是昂贵的。您可能必须使用直联。