Page 1 of 1

[1.4.0] Duplicate search records

Posted: Thu Feb 04, 2010 7:02 pm
by SSJ
Description:
There is the same product in the search results if the product belongs to multiple categories in the same time.
Reported on:
OpenCart V1.4.0
Affected functions:
search and advanced search.
/index.php?route=product/search...
Related files:
catalog/model/catalog/product.php
function getTotalProductsByKeyword() and getProductsByKeyword()
Proposed fix(es):
I try to gave a fix solution for reference,but I think it's not the best way.

getTotalProductsByKeyword()

Code: Select all

   public function getTotalProductsByKeyword($keyword, $category_id = 0, $description = FALSE) {
      if ($keyword) {
         $sql = "SELECT DISTINCT p.product_id FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
         
         if (!$description) {
            $sql .= " AND pd.name LIKE '%" . $this->db->escape($keyword) . "%'";
         } else {
            $sql .= " AND (pd.name LIKE '%" . $this->db->escape($keyword) . "%' OR pd.description LIKE '%" . $this->db->escape($keyword) . "%')";
         }

         if ($category_id) {
            $data = array();
            
            $this->load->model('catalog/category');
            
            $string = rtrim($this->getPath($category_id), ',');
            
            foreach (explode(',', $string) as $category_id) {
               $data[] = "p2c.category_id = '" . (int)$category_id . "'";
            }
            
            $sql .= " AND (" . implode(" OR ", $data) . ")";
         }
         
         $sql .= " AND p.status = '1' AND p.date_available <= NOW()";
         $sql = "SELECT COUNT(*) AS total FROM (" . $sql . ") as un";

         $query = $this->db->query($sql);
      
         if ($query->num_rows) {
            return $query->row['total'];   
         } else {
            return 0;
         }
      } else {
         return 0;   
      }      
   }
getProductsByKeyword()

Code: Select all

   public function getProductsByKeyword($keyword, $category_id = 0, $description = FALSE, $sort = 'pd.name', $order = 'ASC', $start = 0, $limit = 20) {
      if ($keyword) {
      $sql = "SELECT p.*, pd.name AS name, m.name AS manufacturer, ss.name AS stock, (SELECT AVG(r.rating) FROM " . DB_PREFIX . "review r WHERE p.product_id = r.product_id GROUP BY r.product_id) AS rating FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id) LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id) LEFT JOIN " . DB_PREFIX . "stock_status ss ON (p.stock_status_id = ss.stock_status_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND ss.language_id = '" . (int)$this->config->get('config_language_id') . "'";
         
         if (!$description) {
            $sql .= " AND pd.name LIKE '%" . $this->db->escape($keyword) . "%'";
         } else {
            $sql .= " AND (pd.name LIKE '%" . $this->db->escape($keyword) . "%' OR pd.description LIKE '%" . $this->db->escape($keyword) . "%')";
         }
         
         if ($category_id) {
            $data = array();
            
            $this->load->model('catalog/category');
            
            $string = rtrim($this->getPath($category_id), ',');
            
            foreach (explode(',', $string) as $category_id) {
               $data[] = "p2c.category_id = '" . (int)$category_id . "'";
            }
            
            $sql .= " AND (" . implode(" OR ", $data) . ")";
         }
      
         $sql .= " AND p.status = '1' AND p.date_available <= NOW()";
         $sql = "(" . $sql . ") as un";

         $sort = preg_replace('/.*\./' , 'un.' , '.' . $sort);   
         if ($sort) {
            $sql .= " ORDER BY " . $sort;
         } else {
            $sql .= " ORDER BY un.name";   
         }
         
         if ($order == 'DESC') {
            $sql .= " DESC";
         } else {
            $sql .= " ASC";
         }

         if ($start < 0) {
            $start = 0;
         }
      
         $sql .= " LIMIT " . (int)$start . "," . (int)$limit;
         $sql = "SELECT DISTINCT * FROM " . $sql;

         $query = $this->db->query($sql);
      
         return $query->rows;
      } else {
         return 0;   
      }
   }

http://forum.opencart.com/viewtopic.php?f=64&t=10330 in Chinese.

Re: opencart V1.4.0:Duplicate search records

Posted: Thu Feb 04, 2010 7:23 pm
by Daniel
there is a fix for this in the next version. i don;t have time to start copying and pasting solutions across.

Re: opencart V1.4.0:Duplicate search records

Posted: Sat Feb 20, 2010 2:38 am
by boardhopper
Is there a place I can get the code to fix the duplicate search records? If not, is the above code a viable solution?

Re: [1.4.0] Duplicate search records

Posted: Sat Feb 20, 2010 3:53 am
by Qphoria
for now if the above code works then yes its viable

Re: opencart V1.4.0:Duplicate search records

Posted: Sat Feb 20, 2010 2:02 pm
by SSJ
boardhopper wrote:Is there a place I can get the code to fix the duplicate search records? If not, is the above code a viable solution?
Daniel said,the official fix is in the next version, that well be the best way. but for now, the above code is more thoughtful solution for V1.4.0 I think. It gets the not duplicate records by filtering the search results. by the way, it also process the sort function.
It on my opencart sysytem running well. but only for reference.

Re: [1.4.0] Duplicate search records

Posted: Mon Feb 22, 2010 4:12 am
by boardhopper
Thank you to both of you. It seems it will work for me until 4.1 comes out.