简体   繁体   中英

SQL - Query to return the most relevant results from a search

I developed a website with a search box and, when someone searches for any word ("car", for example) I run a query on my database that checks if the searched word is contained in the keywords table. I mean, if is there "car" in the keywords table I'll return on the website the content related with that keyword.

The database has 2 tables used for the search: The contents table (id_content, name, description, alias, ...) and the Keywords table (id_keyword, keyword, id_content), which means that every content have at N keywords, 1 name, 1 description and 1 alias.

But now I want to redefine the search a little better by checking if the search matches not only the keyword but also the name, alias and description. The only problem is that I'm not sure how to do it, since some content will have only a matching keyword, other will have matching name and keyword (just an example) and some will actually have a matching name, description, alias and keyword.

My objective is for my search to retrieve first the full match ones (name, description, alias and keyword), then the 3 match ones, then the 2 match and, finally, the ones that have only 1 match (despite the match being the name, description, alias or keyword).

I'm not sure if I'm being clear enough, feel free to ask for details.

Thank you.


EDIT 1

Function to get the objects by keyword:

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 Code go get a "full match":

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%'

From here, what I can do is to query the full match and, in case there is not enough content (content = object and $limit is the number of results I need), I'll do the query next to the "full match", that would be a "3 match". My problem is that a 3 match can either be a name+description+alias, a name+alias+keyword, description+alias+keyword, etc...


EDIT 2

SQL code to a "1 match" (not sure if the union is correct):

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%'

EDIT 3

Just realized that the "full match" SQL is incorrect, since it will return me the id_object of an object without the searched description (just tested it). Maybe UNION isn't the way to go... Or is it?

Maybe this would work?

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

If keywords are not mandatory, just drop WHERE and add keywords to the relevance counter:

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

Please note that this query is not particularly efficient. If your dataset is really big, you might be better off with a dedicated full-text engine like Sphinx or Solr.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM