Search with LIKE or MATCH.. AGAINST in two columns

Asked

Viewed 3,471 times

14

I have a classified system where I do a search with PHP and Mysql using LIKE in two camps:

campo1 like '' or campo2 like ''

The problem is when I’m looking for something like, "Green car" it doesn’t display anything because "car" is contained in field 1 and "green" in field 2, or even car comes with a word in the middle before "Green".

Could someone give me a tip on how to improve this search?

I tried to use:

SELECT description, title , MATCH ( title, description ) AGAINST ( '$busca' ) AS Score    
FROM qtc_ads WHERE MATCH ( title, description ) AGAINST ( '$busca' )
ORDER BY Score DESC LIMIT 50

However Mysql informs me that the fields do not support this type of search and I do not know if this is the best way.

SQL that I currently use to search on my system:

SELECT * FROM `qtc_ads` AS `qtc_ad` WHERE `status` = 1 AND `title` LIKE '%l200%' (1)
  • Put the SQL you are using.

  • 1

    You are trying to use FULLTEXT search, which seems to be a good way. But for this to work, the columns in question need to have FULLTEXT indexes. Was this the error you mentioned? It would be nice to post the exact message.

  • SELECT * FROM qtc_ads AS qtc_ad WHERE status = 1 AND title LIKE '%car%'

  • You want to search for "car" in the campo1 and campo2 and "green" in the campo1 and campo2?

2 answers

17


A somewhat laborious possibility, but with a more complete result, is to use PHP to divide your search in separate words, and generate the WHERE clause for you:

<?php

   $pesquisa = 'carro verde amassado ';

   // Aqui você pode juntar vários campos no concat.
   $campo = 'CONCAT( title, " ", description, " ", author)';
   // Ou usar um só, mas nesse caso talvez compense um LIKE tradicional
   // $campo = 'title';

   $palavras = explode( ' ', $pesquisa ); // dividindo as palavras pelo espaço
   $palavras = array_filter($palavras); // eliminando ítens vazios

   $where = '';
   $cola = 'WHERE ';

   foreach ($palavras as $palavra) {
      $palavra = trim($palavra); //Removendo espaços em branco
      $palavra = mysql_real_escape_string($palavra); //Precisa da conexao com o banco!
      $where .= $cola.campo.' LIKE "%'.$palavra.'%" ';
      $cola = 'AND ';
   }

   echo htmlentities( $where );
?>

And the result will be:

WHERE
   CONCAT( title, " ", description, " ", author) LIKE "%carro%" AND
   CONCAT( title, " ", description, " ", author) LIKE "%verde%" AND
   CONCAT( title, " ", description, " ", author) LIKE "%amassado%"

(line breaks added for easy reading)

This way the search will find all these results:

O carro amassado era verde
A carroça tinha abacates verdes amassados
Verde carro, amassado tu és

Note that although some lines do not have exact results, it is better to have more things than the user does not find what they need. Keep in mind, however, that the price you pay for complexity is slower research. LIKE and indexes do not work well together.

  • Very good tip. I’m making some adaptations and testing. as soon as I complete the complete code and the result. Thank you very much!

  • I am now trying to apply this to the Kohana Framework.

  • This classic mode I use a lot. I recommend using "complementary" from "CASE WHEN" to sort the search response. Example, "starts with", "ends with", "starts with + space at the beginning", "starts with + space at the end", "has %string%"... and so on..

  • 1

    A fix, swap: $words = $array_filter($words); by $words = array_filter($words); Thanks for the great tip @Bacco, helped me and a lot.

  • @adventistapr corrected in this and the other similar ;)

  • I consider the replace of "spaces" by % in terms of making use of many Likes and using only one LIKE '%green%cars%dented%'

  • 1

    @Eliseub. but that’s why your other question was linked to this one, your problem with word order is the fact that you’re only using one like for several. LIKE '%carros%verdes%amassados%' will never correspond to carros amassados verdes, because % means "any string of characters", nothing more, nothing less.

  • @But that would be a particularity of the application right? In an e-commerce if I search "green cars crumpled" and returns me "green avocados crumpled in papnha", it would not be quite what I hope to receive of reply.

  • @Eliseub. Now we have entered a problem of text interpretation. If one word is enough, you use OR. if you want all three, use AND. And if you don’t like the answer, just don’t use it. For today is what I have to offer as a solution, or fulltext, as Linkei in the other post in comments.

  • @Bacco this same according, I believe that with this and with all the guidelines I can already implement the code in a concise and more efficient way, gratitude.

  • See the fulltext index in the documentation of the desired DB, can be a more pleasant alternative (it already does this thing automatically without needing a lot of like) - But it does not mean that it does not have a performance weight. The best is to test. Keywords: FTS, or Full Text Index / Full Text Search

Show 6 more comments

0

My opinion, is to have only one LIKE in your query, and you can still maintain two fields in your system, where a field would be the object ("Car", "Bike", ..., ...) and in the other field would be a feature ("Green", "Old", ..., ...), then when consulting, vc would concatenate these two fields to put in your query.

Ex: value_um = object; value_two = characteristic; value_query = value_one + value_two LIKE field "' + query value_query + "'%";

Or leave it as it is and use the percentage (%) in the like on both sides, that you will surely find something either in field one or field two.

hope q help.

  • I would need something more objective for the user not to have to type two fields, understand ? Currently the whole system is developed with the feature of only one field for the search. Unfortunately.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.