简体   繁体   English

MySQL-按一个字段中的搜索出现顺序对行进行排序

[英]MySQL - Ordering rows by search occurrences in one field

I am developing an eCommerce website, written in PHP under Symfony2 framework; 我正在开发一个在Symfony2框架下用PHP编写的电子商务网站; 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; 我有一个名为“ searchKeywords”的字段,该字段存储此搜索引擎的特殊关键字。 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. 如果我搜索“孩子”,则应显示商品1和3;如果我搜索“服装”,则应显示商品1和2。
  • 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. 麻烦来了:如果我搜索“绿色服装”,则应显示所有三个产品,因为它们都具有所有关键字,但是,我需要第二个产品比其他产品具有更高的相关性,因为它出现的次数更多,因此产品2应该高于其余产品。

So my question is, is there any way I can achieve that without using PHP code, only MySQL? 所以我的问题是,有什么方法可以不使用PHP代码而仅使用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 . 这样的表将有一个ProductId列和一个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. 该查询的另一个优点是它可以利用ProductKeywords(keyword)上的索引,而您使用存储关键字的方法无法做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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