简体   繁体   中英

Mysql query match against multiple possible characters

I have the following query

SELECT * 
FROM  `articles` 
WHERE (
        (
        UCASE(  `title` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `text` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `source` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `unique` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% musclemass %' )
        )
    )
ORDER BY  `year` DESC

What I wish to do, is change

UCASE(  `tile` ) LIKE UCASE(  '% Fishoil %' )

into

 UCASE(  `title` ) LIKE UCASE(  '%Fishoil %' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil,%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil.%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil:%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil;%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil\'%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil"%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil!%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil?%' )

But this seems to me to make the query unnessarily complex since it'll have to do the match several times. Is there a sort of regex match to match against the "searchterm + special character" in one go?

If so, what would be the best way to match against it?

This is the php code to generate the keyword search string

$specialchars = array(' ',',','.',':',';',mysql_real_escape_string("'"),'"','!','?');
foreach($seek as $searchword)
    {
    foreach($specialchars as $char)
        {
        $seeker[] = "LIKE UCASE(  '%$searchword".$char."%' )";
        }
    $temp = implode(" OR ",$seeker);
    echo $temp;
    }

I suggest that you use regular expressions , since they are much more powerful than the wildcard LIKE syntax. By using regex, you can fit the whole set of conditions into one REGEXP call (per column).

Instead of adding an or clause for each character, use an underscore ( _ ). This acts like a wildcard, except for one thing: it's a place holder for a single char:

SELECT * FROM foo WHERE bar LIKE 'visolie_';

Matches visolie!, visolie:, visolie?, and -because like is case insensitive ViSOliE!, too.

Edit:

To all intents and purposes: there are many good search engines that have been written by Very cleaver people, and are still being further developed by an army of competent programmers. Trying to create your own SE might be a good exercise, but when it really comes down to it, just use CSE .
They've done the hard work for you, and being a developer means being lazy in a clever way. The whole point of open source software and, therefore, the web, is to avoid the necessity of constantly reinventing the wheel.

If you absolutely want to build your own SE, PHP&MySQL is proven technology, but perhaps not the best tool for the job. Try looking into faster DB (NoSQL?) alternatives (MongoDB springs to mind, as long as you're not constantly going to update your data, it's insanely fast. Again: choosing one means loosing the other, your data isn't as safely stored...).
PHP is fairly fast, but takes up a lot of resources compared to, say, C++. I'm not sure if I got this right, but I'm prepared to bet quite a hefty sum of money saying that SE's like google, yahoo! and even crummy old Bing have quite a hefty C(++) codebase somewhere. No scripting language to date can outperform that, (and IMO never will there be a scripting language that can)

It might be worth looking at FULLTEXT

You can do something like this;

SELECT *, MATCH(title,text,source,unique) AGAINST('fishoil for more musclemass') AS `score` FROM `articles` WHERE MATCH(title,text,source,unique) AGAINST('fishoil for more musclemass') ORDER BY `score` DESC, `year` DESC

whcih will return the results most relevant first.

You would have to alter your SQL table too;

ALTER TABLE articles ADD FULLTEXT(title,text,source,unique);

Hope this helps

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