簡體   English   中英

分面搜索計數

[英]Faceted search counting

我想創建多面搜索。 我有一些MySQL表:

**products_table**
id   name          category_set
9    Female.Jeans  157
10   Male.Jeans    157

**fields_table**
id   name
1    Color
2    Gender

**fields_values_table**
id   fieldsid   value
1    1          White
2    1          Black
3    1          Orange
4    1          Green
5    1          Blue
6    2          Male
7    2          Female

**products_to_fields_values**
productid   fields_values_id
9           5
9           7
10          5
10          6

我有php函數來搜索我的產品:

private function get_products ($filter) {

        $per_page   = (isset($filter["show_by"]) && $filter["show_by"] >= 25 && $filter["show_by"] <= 100) ? intval($filter["show_by"]) : 25; 
        $start  = (isset($filter["page_id"]) && intval($filter["page_id"])) ?  ($filter["page_id"] -1)*$per_page : 0;

        $data           = [];

        $search_vids    = false;
        if (isset($filter['vid']) && is_array($filter['vid'])) {

            $in_set = implode(',', array_filter($filter['vid']));

            if (strlen($in_set)) {
                $search_vids = true;
            }
        }

        if ($search_vids) {

            $sql_counter    = 'SELECT COUNT(*) count FROM `products` WHERE 1=1';
            $sql_result = 'SELECT 
                                        P.id,
                                        P.name, 
                                        P.status                                        
                                    FROM `products` P, `products_to_fields_values` V WHERE 1=1';
        } else {

            $sql_counter    = 'SELECT COUNT(*) count FROM `products` WHERE 1=1';
            $sql_result = 'SELECT 
                                        `id`, 
                                        `name`, 
                                        `status`
                                    FROM `products` WHERE 1=1';
        }

        if ($search_vids) {

            $sql_counter    .= ' AND P.id = V.productid AND V.fields_values_id IN ('.$in_set.')';
            $sql_result     .= ' AND P.id = V.productid AND V.fields_values_id IN ('.$in_set.')';
        }

        if (isset($filter['cid']) && intval($filter['cid'])) {

            $sql_counter    .= ' AND FIND_IN_SET(:cid, `category_set`)';
            $sql_result     .= ' AND FIND_IN_SET(:cid, `category_set`)';
            $data[':cid'] = $filter['cid'];
        }

        if (isset($filter['price']['from']) && floatval($filter['price']['from'])) {

            $sql_counter    .= ' AND `price` >= :price_from END ';
            $sql_result     .= ' AND `price` >= :price_from END ';

            $data[':price_from'] = $filter['price']['from'];
        }

        if (isset($filter['price']['to']) && floatval($filter['price']['to'])) {

            $sql_counter    .= ' AND `price` <= :price_to ';
            $sql_result     .= ' AND `price` <= :price_to ';

            $data[':price_to'] = $filter['price']['to'];
        }

        if (isset($filter['q']) && strlen($filter['q']) > 0) {

            $search          = filter_var($filter['q'], FILTER_SANITIZE_STRING);

            $sql_counter    .= ' AND (`name` LIKE concat("%", :search_name, "%")';
            $sql_result     .= ' AND (`name` LIKE concat("%", :search_name, "%")';

            $sql_counter    .= ' OR `product_tag` LIKE concat("%", :search_tag, "%"))';
            $sql_result     .= ' OR `product_tag` LIKE concat("%", :search_tag, "%"))';

            $data[':search_name']  = $search;
            $data[':search_tag']      = $search;
        }   

        $count  = $this->db1->query($sql_counter)->single($data)['count'];

        if ($search_vids) {
            $sql_result             .= ' GROUP BY P.id LIMIT :start, :perpage';
        } else {
            $sql_result             .= ' LIMIT :start, :perpage';
        }

        $data[':start']     = $start;
        $data[':perpage']   = $per_page;

        $rows   = $this->db1->query($sql_result)->resultset($data);
        $pages = ($count >0) ? ceil($count/$per_page) : 0;

        $product_list       = array();
        $fields                 = array();
        $breadcrumbs    = array();

        $cid                    = 0;

        if(count($rows)>0) {
            foreach ($rows as $row) {
                $product_list[]             = $row;
            } 
        }

        $categories                 =   new categories($this->app, $this->user);
        $categories_arr             =   $categories->load();


        if (isset($filter['cid']) && intval($filter['cid'])) { // Categories page

            $sql                = 'SELECT GROUP_CONCAT(fieldid) AS fields_set FROM `fields_to_categories` WHERE `category_set`= :cid';
            $fields_ids     = $this->db1->query($sql)->bind(':cid', $filter['cid'])->single();

            if (isset($fields_ids['fields_set']) && !empty($fields_ids['fields_set'])) {

                $fields         =   new fields($this->app, $this->user);
                $fields         =   $fields->load_controller($fields_ids['fields_set'], false); // False = fields with status = 1
            }

            $breadcrumbs= $categories->getBreadcrumbs($filter['cid']); 

        } else {    

            $breadcrumbs= $categories->getBreadcrumbs($cid); 
        }


        return array(
            'products'          => $product_list,
            'categories'        => $categories_arr["categories"],           
            'filter'                => isset($filter['cid']) && intval($filter['cid']) && isset($fields['fields']) ? $fields['fields'] : '',
            'breadcrumbs'   => isset($breadcrumbs['path']) ? $breadcrumbs['path'] :'',
            'total'             => $count,
            'pages'             => intval($pages),
            'status'                => 1
        );
    }

這會給我圖片: 在此處輸入圖片說明 但是問題在這里:

當我檢查了Male(1個產品)時,藍色應為1。請檢查下圖。 如何修復搜索功能? 在此處輸入圖片說明

您查詢的問題是,即使與單個過濾器匹配,也將返回產品。

由於需要所有過濾器來匹配,因此需要對查詢進行一些更改

這可以通過2種方法實現

  1. 為每個過濾器創建派生表,然后匹配那些派生表
  2. 統計每個產品匹配的過濾器數量,並且僅在匹配特定數量的過濾器時才返回。 小提琴查詢示例

     select pfv.productid, pt.name from fields_table ft inner join fields_values_table fvt on (ft.id=fvt.fieldsid) inner join products_to_fields_values pfv on (pfv.fields_values_id=fvt.id) inner join products_table pt on (pt.id=pfv.productid) inner join product p on (p.productid=pt.id) <-- Assuming product table having price and 1-1 mapping where p.price > 500 and p.categoryid=102 and (ft.name='color' and fvt.value='Blue')or (ft.name='gender' and fvt.value='female') group by pfv.productid, pt.name having count(*)>=2 <--Maintain the count of how many field value filters it should match. In this example we have only 2 filters 

小提琴 (更新小提琴)

| PRODUCTID |         NAME |
|-----------|--------------|
|         9 | Female.Jeans |

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM