1

I was trying to achieve an advanced search using codeigniter framework. I have a search box that has few icons as a search based. Then if the user try to find 1 icon for example an icon of a parking lot it should display all the profiles that has that icon. And if the user click more icons for example parking lot, beer, good for couple...only the profiles that has those characteristics will be displayed..

Database info :

-----------------------------------------------------
place_id            icon_ids
-----------------------------------------------------
1                 1,2,3,4,5,6,7,8
2                 1,2,3,7,9
3                 1,3,4      
4                 1,2,4,5,9,10
5                 1,2,3,5,6,8,9,10
-----------------------------------------------------

MODEL

public function get_search_content($info_id, $search_queries, $query_type, $limit, $start, $action_type)
    {
        if($query_type === 'icons')
        {

            $count_id = explode(',', $info_id);
            $count_id = count($count_id);

            if($count_id > 1)
            {

                $search  = "lai.info_id IN (".$info_id.")";


                $query = $this->db->select('*, c.id AS cat_id, bh.id AS hour_id, bh.place_id AS bh_place_id, c.name AS cat_name, l.place_id AS place_id, lai.place_id AS lai_place_id')

                ->where($search)

                ->join('listing_additional_info lai', 'lai.place_id=l.place_id', 'LEFT')
                ->join('cities cy', 'cy.city_id=l.city_id', 'LEFT')
                ->join('cats c', 'c.parent_id=l.cat_id', 'LEFT')
                ->join('business_hours bh', 'bh.place_id=l.place_id', 'LEFT')
                ->group_by('lai.place_id', 'ASC')
                ->limit($limit, $start)
                ->get('listings l');
            }
            else
            {

                $search  = "FIND_IN_SET('".$info_id."', lai.info_id)";

                $query = $this->db->select('*, c.id AS cat_id, bh.id AS hour_id, bh.place_id AS bh_place_id, c.name AS cat_name, l.place_id AS place_id, lai.place_id AS lai_place_id')
                ->distinct()
                ->where($search)

                ->join('listing_additional_info lai', 'lai.place_id=l.place_id', 'LEFT')
                ->join('cities cy', 'cy.city_id=l.city_id', 'LEFT')
                ->join('cats c', 'c.parent_id=l.cat_id', 'LEFT')
                ->join('business_hours bh', 'bh.place_id=l.place_id', 'LEFT')
                ->group_by('lai.place_id', 'ASC')
                ->limit($limit, $start)
                ->get('listings l');
            }


        }
}

public function m_search_queries($limit, $start)
    {

        // $info_id = $this->input->get('info_id');
        $info_id = $this->input->get('info_id_');

        $search_queries = $this->input->get('q');

        $submit_search = $this->input->get('submit_search');

        if($submit_search == 'true')
        {
            if(!empty($info_id))
            {

                    echo $this->get_search_content($info_id, $search_queries, 'icons', $limit, $start, 'content');


            }
            elseif(!empty($search_queries))
            {
                echo $this->get_search_content($info_id, $search_queries, 'input', $limit, $start, 'content');

            }
            else
            {
                $rs = '';
                $rs .= '<div class="bg bg-info text-white p-3">Sorry, we could not find what you are looking for.</div>';

                echo $rs;
            }
        }

    }

VIEW

<form method="GET" action="<?= base_url().lang(); ?>/search" class="">
        <div class="mb-2" id="add-data-info">
           <?php for($i=1; $i<=13; $i++){ ?>
           <div class="btn add_selector search_add_selector search_add_selector_<?= $i; ?> search_add_info_view">
            <input type="checkbox" value="<?= $i; ?>" class="search_add_info">
            <img id="" class="svg" src="<?= base_url(); ?>theme/myown/img/icon/svg/<?= $i; ?>.svg?<?= time(); ?>" width="28">
           </div>
          <?php } ?>
          <div class="my-2">
          <div class="w-100 border border-muted my-4"></div>
           <input type="hidden" name="query_type" value="icons">
           <button type="submit" name="submit_search" class="btn btn-info btn-lg btn-rounded" value="true">Search</button>
          </div>
        </div>
        <input type="hidden" id="search_selected_additional" name="info_id_">
</form>

SCRIPT

<script>
var _add_info = $('.search_add_selector .search_add_info').on('change', function() {
    var add_info = $('.search_add_selector .search_add_info:checked');

    var _selected = add_info.map(function() {return this.value;}).get().join(',')

    var _checkIfChecked = $('.search_add_selector_'+this.value+' .search_add_info:checked').length > 0;

    if(_checkIfChecked)
    {

     $('.search_add_selector_'+this.value).addClass('selected_info');
    }
    else
    {

     $('.search_add_selector_'+this.value).removeClass('selected_info');
    }

                    $('#search_selected_additional').val(_selected);
                });
</script>

For example: The user has the value selected 1,2,5 then only the places that has at least 1,2,5 icon_ids will be displayed The result should be: 1 4 5

I am using the find_in_set() function it displays pretty well on 1 icon selected.

But for more than 2 icons it displays even if the profile has only 1 characteristic. What I'm trying to achieve is when the user is looking for a specific place that has parking lot, pet shop, beer only the places that has those characteristics will be displayed. Even if some profiles has more than 3 characteristics.

It should be displayed as long as the profile has those 3 characteristics at least.

I am looking forward for your kind help. Thank you so much in advanced everyone!

johnlopev
  • 97
  • 3
  • 16
  • i guess you've to redesign your db and aim to a n:m relationship model take a look here (https://stackoverflow.com/questions/2923809/many-to-many-relationships-examples) - your design is considered as really bad - because you aren't using the strenghts of a modern RDBMS (you are breaking the first normal form...) - if you resist and want to stay at your version - for whatever reason - take a look here https://stackoverflow.com/questions/5015403/mysql-find-in-set-with-multiple-search-string – Atural Dec 13 '18 at 18:28
  • Possible duplicate of [MySQL find\_in\_set with multiple search string](https://stackoverflow.com/questions/5015403/mysql-find-in-set-with-multiple-search-string) – Atural Dec 13 '18 at 18:29
  • @sintakonte Thanks for your reply. I went to the link the have provided. Could you give at least a sample code for it. I don't quite understand this one: `WHERE CONCAT(",", `setcolumn`, ",") REGEXP ",(val1|val2|val3),"` It seems not working on my end. I am really newbie for this framework. Thanks a lot! – johnlopev Dec 13 '18 at 19:02
  • I have this code in my model: `$search = "FIND_IN_SET('".$info_id."', lai.info_id)"; $query = $this->db->select('*, CONCAT(",", "lai.info_id", ",") REGEXP ",('.$info_id.'|'.$info_id.'|'.$info_id.'),"') ->where($search) ->group_by('lai.place_id', 'ASC') ->limit($limit, $start) ->get('listings l');` – johnlopev Dec 13 '18 at 19:08
  • @johnlopev this `WHERE CONCAT(",", `setcolumn`, ",") REGEXP ",(val1|val2|val3),"` is on mySQL, you'd need to pass the three values into a query, which is not particular to CodeIgniter.. it's plain PHP. Having said that, I'd strongly suggest you re-think and re-model your database to make better use of your RDBMS... better to do it now, early, than later when you'll experience much more pain (see @sintakonte 's first comment) – Javier Larroulet Dec 13 '18 at 19:43
  • Instead of over-complicating the query just us multiple wheres. – Sherif Salah Dec 13 '18 at 23:26
  • Here is my table structure: `places` table has `(place_id, place_name)` and I have I have `icons` table `(id, place_id, icon_ids)` where `icon_ids` has inserted from the text view that generates the comma-separated values. Please let me know if it doesn't meet the RDBMS... Thanks – johnlopev Dec 14 '18 at 04:01

1 Answers1

2

I've create this and tested it in my environment and it works like a charm:

    $this->db->select('whatever')->from('your_table');
    $this->db->group_start();
    foreach($selected_values as $value)
    {
        $this->db->where("find_in_set($value, icon_ids)");
    }
    $this->db->group_end();
    $result = $this->db->get()->result_array();

I tested it again with your values and it works just fine on (1,2,5) it shows (1,4,5)

Sherif Salah
  • 2,085
  • 2
  • 9
  • 21
  • Uh oh!.. I think it's working I was just damn doesn't realize that it did work! Thanks bro! You saved my day! :D – johnlopev Dec 14 '18 at 07:33