简体   繁体   中英

MySQL - Ordering rows by search occurrences in one field

I am developing an eCommerce website, written in PHP under Symfony2 framework; and currently I need to develop a method to provide the users a field for searching products.

In each product; I have a field named 'searchKeywords' which stores special keywords for this searching engine; so, suppose that we have the following product data:

ProductId - keywords
----------------------
1           child costume
2           costume green
3           child green
  • If I search for 'child', products #1 and #3 should be shown, If I search for 'costume', products #1 and #2 should be displayed.
  • Here comes the trouble: if I search for 'costume green', all three products should be shown because all of them have all the keywords, BUT, I need that the #2 product has more relevance than the others because it has more search occurrences, so product #2 should be above the rest.

So my question is, is there any way I can achieve that without using PHP code, only MySQL? Thanks.

You can do this if each of your input keywords is in a separate variable. If your keywords were separated by commas instead of spaces:

select . . .
where find _in_set($keyword1, keywords) > 0 or
      find _in_set($keyword2, keywords) > 0 or
      find _in_set($keyword3, keywords) > 0 
order by (find _in_set($keyword1, keywords) > 0 +
          find _in_set($keyword2, keywords) > 0 +
          find _in_set($keyword3, keywords) > 0
         );

With spaces, you can do:

where concat(' ', $keywords, ' ') like concat(' %', $keyword1, '% ') or
      concat(' ', $keywords, ' ') like concat(' %', $keyword2, '% ') or
      concat(' ', $keywords, ' ') like concat(' %', $keyword3, '% ')
order by concat(' ', $keywords, ' ') like concat(' %', $keyword1, '% ') +
         concat(' ', $keywords, ' ') like concat(' %', $keyword2, '% ') +
         concat(' ', $keywords, ' ') like concat(' %', $keyword3, '% ')

The additional spaces are to prevent "red" from matching "redo".

However, you shouldn't be storing keywords in a list like this. You should have an association/junction table. Such a table would have a column for ProductId and a column for keyword . Multiple keywords would be stored on different rows. With this table, the query would simply be:

from ProductKeywords pk
where pk.keyword in ($keyword1, $keyword2, $keyword3)
group by pk.ProductId
order by count(*) desc;

Another advantage to this query is that it can take advantage of an index on ProductKeywords(keyword) , which you can't do with your method of storing the keywords.

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