SQL - 查询以从搜索中返回最相关的结果

时间:2014-08-25 10:14:31

标签: php mysql sql search

我开发了一个带搜索框的网站,当有人搜索任何单词时(例如“car”),我在我的数据库上运行一个查询,检查搜索到的单词是否包含在关键字表中。我的意思是,如果关键字表中有“汽车”,我会在网站上返回与该关键字相关的内容。

数据库有2个用于搜索的表:内容表(id_content,name,description,alias,...)和关键字表(id_keyword,keyword,id_content),这意味着每个内容都有N个关键字,1个名字,1个描述和1个别名。

但现在我想通过检查搜索是否匹配关键字以及名称,别名和描述来更好地重新定义搜索。唯一的问题是我不知道该怎么做,因为一些内容只有匹配的关键字,其他的将有匹配的名称和关键字(只是一个例子),有些内容实际上会有匹配的名称,描述,别名和关键字。

我的目标是我的搜索首先检索完全匹配的(名称,描述,别名和关键字),然后是3个匹配的,然后是2个匹配,最后是只有1个匹配的那个(尽管匹配是名称,描述,别名或关键字)。

我不确定自己是否足够清楚,随时可以询问详细信息。

谢谢。


编辑1

按关键字获取对象的函数:

public function get_object_id_by_keyword($keyword, $limit = 3){
    $id = "";
    $sql  = "SELECT id_object FROM addons_keywords WHERE keyword = '".$keyword."' limit " . $limit;
    $res  = $this->db->query($sql);
    if($res->num_rows() == 1){
        $id = $res->row(0)->id_object;
    }
    else{
        $id = array();
        for($i=0; $i<$res->num_rows(); $i++){
            array_push($id, $res->row($i)->id_object);
        }
    }

    return $id;
}

SQL代码获得“完全匹配”:

SELECT id_object
FROM addons_keywords 
WHERE keyword = 'searched'

UNION 

SELECT id_object
FROM objects
WHERE name LIKE '%searched%'
AND description LIKE '%searched%'
AND alias LIKE '%searched%'

从这里,我可以做的是查询完整匹配,如果内容不足(content = object和$ limit是我需要的结果数),我会在旁边查询“完全匹配”,这将是一场“三场比赛”。我的问题是3匹配可以是名称+描述+别名,名称+别名+关键字,描述+别名+关键字等...


编辑2

SQL代码为“1匹配”(不确定联合是否正确):

SELECT id_object 
FROM addons_keywords 
WHERE keyword = 'searched'

UNION

SELECT id_object
FROM objects
WHERE name LIKE '%searched%'
OR description LIKE '%searched%'
OR alias LIKE '%searched%'

编辑3

刚刚意识到“完全匹配”SQL是不正确的,因为它会返回一个没有搜索描述的对象的id_object(只是测试它)。也许UNION不是要走的路......或者是它?

1 个答案:

答案 0 :(得分:3)

也许这会起作用?

SELECT 
    id_object,
    (name LIKE '%searched%')
        + (description LIKE '%searched%')
        + (alias LIKE '%searched%')
        AS score
    FROM objects
    WHERE id_object IN (
        SELECT id_object 
           FROM addons_keywords 
           WHERE keyword = 'searched'
    )
    HAVING score > 0  -- remove this to allow keyword-only matches
    ORDER BY score DESC

如果关键字不是强制性的,只需删除WHERE并将关键字添加到相关性计数器:

SELECT 
    id_object,
    (name LIKE '%searched%')
        + (description LIKE '%searched%')
        + (alias LIKE '%searched%')
        + (id_object IN (
            SELECT id_object 
               FROM addons_keywords 
               WHERE keyword = 'searched'
            )
          )
        AS score
    FROM objects
    ORDER BY score DESC

请注意,此查询效率不高。如果您的数据集非常大,那么使用像Sphinx或Solr这样的专用全文引擎可能会更好。