Php 使用Sphinx的高级MySQL搜索

Php 使用Sphinx的高级MySQL搜索,php,mysql,search,sphinx,Php,Mysql,Search,Sphinx,为了提高搜索引擎的速度,我经历了很多死路一条,最后我决定转向斯芬克斯,不管是好是坏。所以我们的网站是一个基于定制MVC框架的在线商店 当用户搜索乳清蛋白时,我们会为他提供这些关键词的搜索结果以及过滤的类别和属性 假设一种名为100%乳清蛋白的产品属于蛋白质类,该类产品具有指定的特性: 口味-巧克力、香草、草莓 包装尺寸-1千克、2千克、5千克 颜色-蓝色、红色、白色、黑色 产品100%乳清蛋白具有以下值: 口味-巧克力、草莓 包装尺寸-2公斤,5公斤 颜色-红色 当用户搜索一个短语乳清蛋白时,我

为了提高搜索引擎的速度,我经历了很多死路一条,最后我决定转向斯芬克斯,不管是好是坏。所以我们的网站是一个基于定制MVC框架的在线商店

当用户搜索乳清蛋白时,我们会为他提供这些关键词的搜索结果以及过滤的类别和属性

假设一种名为100%乳清蛋白的产品属于蛋白质类,该类产品具有指定的特性:

口味-巧克力、香草、草莓 包装尺寸-1千克、2千克、5千克 颜色-蓝色、红色、白色、黑色 产品100%乳清蛋白具有以下值:

口味-巧克力、草莓 包装尺寸-2公斤,5公斤 颜色-红色 当用户搜索一个短语乳清蛋白时,我们会向他显示包含该短语的所有产品,并且我们会过滤我们的类别,以仅显示包含该短语产品的产品以及包含该短语产品的属性。显示的例子你可以看你可以使用谷歌翻译,因为该网站是保加利亚语

这是我的Sphinx配置文件

source content {

    sql_query_pre           =   SET NAMES utf8
    sql_query               = \
                            SELECT p.*, p.product_id, \
                            m.man_name, m.man_image_location, m.man_seo_url, pcr.ctg_id, \
                            gal.image_filelocation, pir.item_id, pav.atr_id \
                            from 3w_products p \
                            INNER JOIN 3w_products_gallery gal ON gal.product_id = p.product_id AND (gal.show_order = 1 OR gal.show_order = NULL)\
                            LEFT OUTER JOIN 3w_manufacturers m ON m.man_id = p.man_id \
                            LEFT OUTER JOIN 3w_products_cat_rel pcr ON pcr.product_id = p.product_id \
                            LEFT OUTER JOIN 3w_product_item_rel pir ON pir.product_id = p.product_id \
                            LEFT OUTER JOIN 3w_product_attribute_values pav ON pav.product_id = p.product_id \
                            ;
    #attribute declaration  
    sql_attr_uint           = product_id
    sql_attr_uint           = man_id
    sql_attr_uint           = product_notinstock
    sql_field_string        = product_name
    sql_field_string        = man_name
    sql_field_string        = product_code
    sql_field_string        = product_seo_url
    sql_field_string        = image_filelocation
    sql_field_string        = product_intro_plain
    sql_field_string        = product_second_name
    sql_field_string        = product_price
    sql_field_string        = product_price_promo
    sql_field_string        = product_promo_expire_date
    sql_field_string        = product_views
    sql_field_string        = product_rating
    sql_field_string        = product_date_added
    sql_field_string        = product_price_returned
    sql_field_string        = man_image_location
    sql_field_string        = man_seo_url


    sql_attr_uint          = product_exquisite
    sql_attr_uint          = product_votes
    sql_attr_uint          = product_returned


    sql_attr_multi          = uint item_id from field; items
    sql_attr_multi          = uint atr_id from field; attributes
    sql_attr_multi          = uint ctg_id from field; categories
}
以及PHP代码:

        require_once("extensions/libs/sphinx/sphinxapi.php");
        if ($params['order']) {
            switch ($params['order']) {
                case 'newest':
                    $order = 'product_notinstock ASC, product_id DESC';
                    break;
                case 'priceup':
                    $order = 'product_notinstock ASC, p.product_price_sell ASC';
                    break;
                case 'pricedown':
                    $order = 'product_notinstock ASC, p.product_price_sell DESC';
                    break;
                case 'views':
                    $order = 'product_notinstock ASC, product_views DESC';
                    break;
                case 'promoted':
                    $order = 'product_notinstock ASC, p.product_price_promo DESC';
                    break;
                case 'exquisite':
                    if (!$params['search']) {
                        $order = 'p.product_notinstock ASC, p.product_exquisite DESC, p.product_views DESC';
                        break;
                    } else {
                        $order = "product_notinstock ASC, @weight DESC, product_views DESC ";  
                        break;
                    }
                default:
                    $order = "product_notinstock ASC, @weight DESC, product_views DESC "; 
                    break;
            }
        }

        $phrase = $params['search'];
        $page = isset($_GET['page']) ? $_GET['page'] : 1;

        $client = new SphinxClient();
        $client->SetLimits($params['offset'], $params['limit']);
        $client->SetSortMode(SPH_SORT_EXTENDED, $order);
        $client->SetRankingMode(SPH_RANK_SPH04);
        $client->SetMatchMode(SPH_MATCH_EXTENDED);

        $client->SetFieldWeights(array('product_code'=>30, 'product_name'=>15, 'product_meta_data'=>2));
        if($params['returned']) $client->setFilter('product_returned', array($params['returned']));
        if($params['man_id']) $client->setFilter('man_id', array($params['man_id']));
        if($params['ctg_id']) $client->setFilter('ctg_id', array($params['ctg_id']));
        if($params['properties']) 
            foreach($params['properties'] as $prop_id => $prop) $client->setFilter('item_id', array_keys($prop['items']));
        if($params['attribute']) $client->setFilter('atr_id', array($params['attribute']['atr_id']));

        $phrase = str_replace(" - ", "-", $phrase);
        $query = '@product_name ('.$phrase.') | @product_meta_data ('.$phrase.') | @product_code ('.$phrase.')';
        $res = $client->Query($query, 'products');
        $products = array();
        foreach($res['matches'] as $id => $product) {
            $product['attrs']['product_id'] = $id;
            $products[] = $product['attrs'];
        }
        $return['result'] = $products;
        $return['finded'] = $res['total_found'];

        return $return;
但是,这会返回正确的结果。但我需要将其他一些查询迁移到Sphinx,以进一步提高速度

查询1-类别:

SELECT c.ctg_id, c.ctg_parent_id, c.ctg_name, 
c.ctg_seo_url, count(distinct pcr.product_id) products 
FROM 3w_product_categories c 
LEFT JOIN 3w_products_cat_rel pcr ON pcr.ctg_id = c.ctg_id 
LEFT JOIN 3w_products p ON p.product_id = pcr.product_id 
WHERE ( MATCH (p.product_code,p.product_meta_data) 
AGAINST ('+whey* +protein*' IN BOOLEAN MODE)) 
GROUP BY c.ctg_id ORDER BY c.ctg_name 
问题2-制造商:

SELECT m.man_id, m.man_name, 
m.man_seo_url, count(distinct p.product_id) products 
FROM 3w_manufacturers m 
INNER JOIN 3w_products p ON p.man_id = m.man_id 
WHERE ( MATCH (p.product_code,p.product_meta_data) 
AGAINST ('+whey* +protein*' IN BOOLEAN MODE)) 
GROUP BY m.man_id ORDER BY m.man_name ASC 
查询3-属性及其项:

SELECT pi.item_id, pi.item_name, pi.item_slug, pp.prop_id, 
pp.prop_name, pp.prop_slug, count(distinct pir.product_id) products 
FROM 3w_property_items pi 
LEFT JOIN 3w_product_item_rel pir ON pir.item_id = pi.item_id 
INNER JOIN 3w_products p ON p.product_id = pir.product_id 
LEFT JOIN 3w_properties pp ON pp.prop_id = pi.prop_id 
WHERE ( MATCH (p.product_code,p.product_meta_data) 
AGAINST ('+whey* +protein*' IN BOOLEAN MODE)) 
ORDER BY pp.prop_name ASC, pi.item_name ASC 
我有查询4,它是针对产品属性的,但它在某种程度上等同于查询3

所以我的问题是-如何在Sphinx索引中实现所有这些查询?当我打字时,脑海中浮现出另一个问题——当管理员插入/编辑产品时会发生什么?斯芬克斯指数是如何更新的?克朗每天晚上

我不介意重写所有的搜索引擎,因为我知道它不是完美的组织


谢谢你抽出时间

考虑运行EXPLAIN EXTENDED,然后为每个查询显示警告,并将结果粘贴到此处。老实说,这个问题似乎有点懒散,对任何人来说都很难理解。您似乎知道如何将一个查询转换为sphinx,对其他查询再次执行相同的操作;而不仅仅是要求人们为你“编写代码”。最后,关于更新的问题应该是分开的,虽然很漂亮,但是如果你在网上找一些教程,你可以自己回答