Хелпер не помогает обойти 20000 товаров, какие еще есть варианты? Есть решение

Что захотел - получить на главной выборку в количестве 10 из ВСЕХ товаров с фильтрацией по заполненности определенной характеристики и по её величине.

Добавил хелпер:

class shopMyCustom extends waAppViewHelper
{
    public static function hGetProductFeatureValueByCode($product_id, $feature_code)
    {
        $features=new shopProductFeaturesModel();
        $vals=$features->getValues($product_id);
        return $vals[$feature_code];
    }
}

Вывожу на главной, добавляя условие на заполненность характеристики и на величину (характеристика заполнена у 3000 товаров и фильтруя по величине, получается всего 500 товаров):

{$products = $wa->shop->products(null,null,20000)}
{foreach $products as $p}
    {$discont=shopMyCustom::hGetProductFeatureValueByCode($p.id,'discont')} 
    {if $discont > 0 && $discont < 8}
        {$p.name} - {$discont}
    {/if}
{/foreach}

Надеялся что работа через хелпер поможет, ан нет, на 20000 товарах вывод ОДНОЙ характеристики обваливает сайт. Как еще выцепить эти товары, при том, что нужно показать всего 10-20??

7 ответов

  • 3
    Павел Гордовой 11 августа 2016 12:29 #

    Ищите другое решение или раз в сутки делайте индексацию, временную таблицу и из нее выводите.

  • 1
    Genasyst 11 августа 2016 13:42 #

    Тут поможет сложный sql запрос! примерно из 6 таблиц))))

    • +3
      Павел Гордовой Павел Гордовой 11 августа 2016 14:27 #

      который вообще нахрен повесит бд
      хотите скорости - создавайте свою индексную таблицу

      • +1
        Сергей Сыроежкин Сергей Сыроежкин 11 августа 2016 15:52 #

        а разве не из трех таблиц? характеристика известна и будет всегда одна и та же, да еще и текстовое поле. неужели повесит? я так понял, что в данном случае вешается фронт??? или нет?

        На хостцмс по 50к товаров легко база шуршала, как раз именно тоже самое делала... там таблица товаров+таблица характеристик+таблица связей...

        • +2
          Павел Гордовой Павел Гордовой 11 августа 2016 16:13 #

          здесь больше таблиц. у вэбасиста сложная структура характеристик
          можно, конечно, статикой по вставлять некоторые данные в запросы, но все же - лучше и логичней как я описал.
          раз уж Вы лезете в индивидуальные запросы к БД - чего не сделаете как я говорю?

          • +1
            Сергей Сыроежкин Сергей Сыроежкин 11 августа 2016 16:22 #

            Исходя из логики требуемого, подошел бы модуль или плагин типа "Товары 2001 г. выпуска" или например "Товары со скидкой" (у меня как раз скидка сделана текстовой характеристикой), но почему-то штатного нет, а список товаров с фильтром по характеристике в моей версии сделать низзя, говорят в семерке есть это. И как же там интересно это делается?

            • +1
              Genasyst Genasyst 11 августа 2016 16:43 #

              плагины ресурсы тоже нехило кушают в больших магазинах!

            • +2
              Genasyst Genasyst 11 августа 2016 16:44 #

              Вечером напишу запрос тебе!

              • +1
                Сергей Сыроежкин Сергей Сыроежкин 11 августа 2016 17:21 #

                я весь в интриге!! жду...

                • +1
                  Genasyst Genasyst 11 августа 2016 21:12 #

                  Опишите подробнее по каким признакам выбирать продукты! Так то там есть таблица в которой есть уже все данные для выборки по значению характеристики продуктов!

                  • +1
                    Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 00:47 #

                    по каким по каким - у которых ЗАПОЛНЕНА характеристика и у которых она в интервале, например от 0 до 8. харакетристика - текстовое поле.

      • +2
        Genasyst Genasyst 11 августа 2016 16:37 #

        А если плясать от значения характеристики то не повесит бд!

    • +2
      Syrnik.com Syrnik.com 12 августа 2016 00:14 #

      Если использовать мозг, то тут поможет посмотреть класс shopProductsCollection, а не возведение своего огорода

  • 1
    Genasyst 11 августа 2016 21:17 #

    О

  • 3
    Genasyst 11 августа 2016 21:17 # Решение



    select * from shop_product_features where feature_id =  24 and feature_value_id = 83 order by id limit 0, 10
    • +1
      Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 11:51 #

      83 - это что? походу еще надо табличку присоединить.

      наверное, все вносимые значения еще храняться в другой табличке, не могу посмотреть, т.е. если такая скидка уже вбивалась в это поле , то у нее уже есть АЙДИ. мда уж.. логика... АЙДИ для ЗНАЧЕНИЙ характеристик плюс свзяь с еще однйо таблицей. точно 6 таблиц как тут ктото говорил

      <span>характеристика равна 0 - feature_value_id =21
      </span><span>характеристика равна 1 - </span><span>feature_value_id =41</span><span>
      </span><span>характеристика равна 2 - </span><span>feature_value_id =63</span><span>
      </span><span>характеристика равна 3 - </span><span>feature_value_id =42</span><span></span><span>
      </span><span>характеристика равна 4 - </span><span>feature_value_id =37</span><span></span><span></span>
    • +1
      Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 12:12 #

      -

      мне кажется, ORDER BY надо делать по product_id, т.к. провел эксперимент - сохраняю товар с новым, ранее не примененным ЗНАЧЕНИЕМ характеристики - в таблице shop_product_features создается новая строка... карл?

      т.е. если предположить гипотетику что оператор откроет товар и начнет менять одну характеристику и сохранять и так 1000 раз, то указанная выше таблица вырастет на 1000 строк!!!!

      на практике конечно не так печально, вбил характеристику и они по идее дальше постоянны, но вот в моем случае скидка на товар сделана как характеристика, а скидка имеет право меняться..

      и SELECT сделать не как *, а как SELECT product_id - нужно из жалкой таблицы только айди товара, больше оттуда ничего не вытянуть)))

    • +1
      Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 13:07 #

      почему-то урл не могу вытянуть...

      • +1
        Genasyst Genasyst 12 августа 2016 18:22 #

        используй класс shopProduct($product_id) там все данные по товару грузятся

  • 1
    Сергей Сыроежкин 12 августа 2016 00:51 #

    я даже не сомневался, что прямой запрос в базу экономенее на несколько порядков! ибо дергать готовые массивы, отталкиваясь от систменых переменных и потом их же копошить опять же штатными обработками как видно привело к банальной классике!!! Гена Рыжов = ГЕНИЙ!

    • +1
      Genasyst Genasyst 12 августа 2016 01:02 #

      ибо все ORM говно и жрут память, а ресурс запроса не весит ничего, пока из него не пишешь массив!

      Советую попробовать:

      $col = new shopProductsCollection();

      $col->filters(array($feature['code'] => $feature_value['id']));

      $products = $col->getProducts("*", 0,10);

      Вдруг отработает!

    • +2
      Genasyst Genasyst 12 августа 2016 01:10 #

      Вот как на на моделях такой запрос составить?



      SELECT
        B.ID,
        B.ACCOUNT_ID,
        B.OPTION_ID,
        I.OPTION_COUNT,
        B.QUANTITY,
        B.CAN_BUY,
        O.USE_BASKET_IMAGE,
        O.USE_BASKET_IMAGE_DESC,
        B.IMAGE_ID,
        B.FROM_SITE_COMPANY_ID,
        DECODE(
                        DECODE(
                          P.COMPANY_ID, 4697668, DECODE(
                            (SELECT 1 FROM SK_OPTION_ORG_TYPE OOT WHERE OOT.OPTION_ID = O.ID AND OOT.LID = 'ru' AND OOT.ORG_TYPE_ID = 'F'), 1, 1, 0)
                          ,1)
                        ,1, DECODE(
                        O.BASKET_NAME, '', (P.NAME||DECODE(I.NAME, '', '', ': ')||I.NAME||DECODE(O.NAME, '', '', ': ')||O.NAME), O.BASKET_NAME)
                        , P.NAME||' '||DECODE(O.EDITION_TYPE_ID,1,'Базовая лицензия',22,'Продление лицензии')
                      ) as PROGRAM_NAME,
               DECODE(
                        DECODE(
             P.COMPANY_ID,
             4697668,
             DECODE(
            (SELECT 1 FROM SK_OPTION_ORG_TYPE OOT WHERE OOT.OPTION_ID = O.ID AND OOT.LID = 'ru' AND OOT.ORG_TYPE_ID = 'F'),
             1, 1, 0)
            ,1)
            ,0,
            Round(O.LICENCE_PERIOD/365)||  GET_NUMBER_ENDING(Round(O.LICENCE_PERIOD/365),' год ',' года ',' лет ')||' | '  ||O.SUBSCRIPTION_LC||
              GET_NUMBER_ENDING(O.SUBSCRIPTION_LC,' устройство ',' устройства ',' устройств ')
                      ) as PROGRAM_DOP_NAME,
        P.NAME as PROGRAM_NAME0,
        O.NAME as OPTION_NAME0,
        I.NAME as ITEM_NAME0,
        P.FREE_DESC,
        I.ID as ITEM_ID,
        P.ITEM_COUNT,
        PL.VISIBLE AS PROGRAM_VISIBLE,
        CURL.FULL_NAME AS CURRENCY_NAME,
        CURL.FORMAT_STRING AS CURRENCY_PRINT,
        P.ID as PROGRAM_ID,
        P.BUNDLE,
        P.COMPANY_ID as PROGRAM_COMPANY_ID,
        B.PUT_OFF, O.WEIGHT, O.IS_NAME, O.IS_COMPANY, O.IS_EMAIL, O.IS_ZIPCODE,
        DECODE(O.MATERIAL_DELIVERY, 'Y', O.IS_LOCATION, 'Y') as IS_LOCATION,
        O.IS_ADDRESS, O.IS_PHONE, O.IS_INN, O.IS_OWNER_TYPE, O.PARAM1, O.PARAM2, O.PARAM3,
        O.PARAM1_ERROR_TEXT, O.PARAM1_LENGTH, O.PARAM1_LENGTH_ERROR_TEXT,
        O.PARAM2_ERROR_TEXT, O.PARAM2_LENGTH, O.PARAM2_LENGTH_ERROR_TEXT,
        O.PARAM3_ERROR_TEXT, O.PARAM3_LENGTH, O.PARAM3_LENGTH_ERROR_TEXT,
        DECODE(BO.VALUE,null, DECODE(SBOC.VALUE,null,DECODE(get_hmax_mnogoru(P.ID, 'ru'),0,O.MNOGO_RU_KOEFF,get_hmax_mnogoru(P.ID, 'ru')),SBOC.VALUE), BO.VALUE) as MNOGO_RU_KOEFF,
        O.MATERIAL_DELIVERY, O.AUTHOR_DELIVER, O.BUNDLE_TYPE, B.COUPON, O.SHIP_ON_CD,
        DECODE(PLB.PROGRAM_ID, NULL, 'N', 'Y') AS CAN_BUY_LANG,
        CL.NAME as PROGRAM_COMPANY_NAME,
        DECODE(BIP.IN_PRICE, NULL,0,BIP.IN_PRICE) AS IN_PRICE, DECODE(BIP.IN_QUANTITY,NULL,0,BIP.IN_QUANTITY) AS IN_QUANTITY,
        DECODE(BIP.CURRENCY, NULL, 'x', BIP.CURRENCY) AS IN_CURRENCY, LOCK_BASKET,
        B.OFFER_ID, O.WITHOUT_NDS, O.AGREEMENT_ID, O.NOT_SUM_WEIGHT,
        NVL((SELECT TRANSFER_METHOD FROM SK_OPTION_TRANSFER_METHOD WHERE LID='ru' AND OPTION_ID=O.ID), 'T') AS TRANSFER_METHOD,
        B.BY_BONUS_OPTION_ID ,
        P.CATALOG_DESC_TYPE,
        P.CATALOG_DESC,
        P.SHORT_DESC,
        O.DESCRIPTION as OPTION_DESC,
        O.DESCRIPTION_TYPE as OPTION_DESC_TYPE,
        -- decode(NVL(O.IMAGE_ID,0),0,P.CATALOG_IMAGE_ID,O.IMAGE_ID) as CATALOG_IMAGE_ID,
        P.CATALOG_IMAGE_ID,
        O.IMAGE_ID  as OPTION_IMAGE_ID,
        I.IMAGE_ID  as ITEM_IMAGE_ID,
        P.IMAGE_ID  as PROGRAM_IMAGE_ID,
                      DECODE(NVL(BN.SORT, 1), 1, 'Y', 'N') as BUNDLE_MAIN_PRODUCT
       FROM
        SK_BASKET_CART B
                      left join sk_bundle bn on bn.BUNDLE_OPTION_ID = b.OPTION_ID
                      left join sk_option bno on bno.id = bn.OPTION_ID
                      join sk_option o on O.ID = nvl(bn.OPTION_ID, b.OPTION_ID)
                      join sk_item i on O.ITEM_ID=I.ID
                      join sk_program p on I.PROGRAM_ID=P.ID
                      join SK_PROGRAM_LANG PL on PL.PROGRAM_ID=P.ID and  PL.LID='ru'
        join SK_COMPANY C on C.ID=P.COMPANY_ID
                      join SK_COMPANY_LANG CL on CL.COMPANY_ID=C.ID AND CL.LID=PL.LID
        join SK_CURRENCY_LANG CURL on CURL.CURRENCY='RUR' AND CURL.LID='ru'
      
        left join (SELECT * FROM SK_BONUS_OPTION WHERE ACTIVE = 'Y' and SYSDATE between PERIOD_FROM and PERIOD_TO) BO on O.ID=BO.OPTION_ID
        left join (SELECT bo.value, opt.id FROM SK_PROGRAM P, SK_ITEM I, SK_OPTION OPT, SK_BONUS_OPTION BO
         WHERE BO.ACTIVE = 'Y' and SYSDATE between BO.PERIOD_FROM and BO.PERIOD_TO
         and P.ID=I.PROGRAM_ID and I.ID=OPT.ITEM_ID and BO.COMPANY_ID=P.COMPANY_ID
        ) SBOC on O.ID=SBOC.ID
        left join (SELECT PL.PROGRAM_ID
         FROM SK_PROGRAM_LANG PL, SK_PROGRAM P, SK_COMPANY C, SK_COMPANY_LANG CL
         WHERE PL.PROGRAM_ID=P.ID AND C.ID=P.COMPANY_ID AND CL.COMPANY_ID=C.ID
          AND PL.LID='ru' AND CL.LID=PL.LID
          AND C.ACTIVE='Y' AND CL.AUTHOR='Y' AND PL.ACTIVE='Y'
        ) PLB on PLB.PROGRAM_ID=P.ID
                      left join SK_BASKET_IN_PRICE BIP on BIP.BASKET_CART_ID=B.ID
       WHERE
        B.ACCOUNT_ID=165997731
                      AND (BN.ACTIVE='Y' or BN.ACTIVE IS NULL)
        AND O.ACTIVE='Y'
        AND I.ACTIVE='Y'
        AND PL.ACTIVE='Y'
        AND C.ACTIVE='Y' AND CL.AUTHOR='Y'
        AND (
                          B.BUNDLE_OPTION_ID IS NOT NULL
                          OR
                          (
                              B.BUNDLE_OPTION_ID IS NULL
                              AND NOT EXISTS ( SELECT 1 from SK_BASKET_CART BBN WHERE BBN.ACCOUNT_ID = B.ACCOUNT_ID AND BBN.BUNDLE_OPTION_ID = B.OPTION_ID )
                          )
      
                      )
       ORDER BY
                      BN.SORT nulls last,
        DECODE(O.ID, 905, 1, 0), 
        PROGRAM_NAME
  • 1
    ITFrogs 12 августа 2016 15:02 #

    Ннужно внутри цикла с перебором всех товаров добавить еще цикл с перебором характеристик по каждому товару с обязательным запросом в базу на каждую характеристику. Это должно помочь, да и модераторам нравится.

    • +1
      Syrnik.com Syrnik.com 12 августа 2016 15:05 #

      Жестокий ты какой :) Ну, пусть будет пятничный тредик

    • -1
      Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 16:21 #

      Дыг все сделано уже, через ПРАВИЛЬНЫЙ хелпер ОДИН запрос в базу и вывод 10 товаров со скидкой. девиз - долой ORM помог и решил этот день!

      Вроде что-то похожее видел в WA-маркетплейсе, что-то там с чем-то по поводу характеристик??? Ну щас выложу код, немного обвалим цены как говорится... Небольшая черная пятница для продаванов, как вам?)))

  • 1
    Genasyst 12 августа 2016 18:09 # Решение
    Выполнение SQL-запросов, записанных в явном виде
    Во фреймворке доступны два основных метода модели для выполнения SQL-запросов — query и exec. Первым параметром они принимают SQL-запрос, а вторым — необязательный массив значений для плейсхолдеров.
    
    Пример:
    
    $model->query("SELECT * FROM ".$this->table." WHERE id = i:id", array('id' => $id));
    Пояснения к примеру:
    
    i:id — это именованный плейсхолдер, в котором i указывает на тип Integer (то есть значение, полученное из массива, будет приведено к целочисленному типу);
    id — ключ в массиве значений;
    array('id' => $id) — массив значений.
    Доступные для использования типы значений плейсхолдеров:
    
    's' — String
    'i' — Integer
    'b' — Boolean
    'f' — Float/Double
    Если тип плейсхолдера явно не указан (например, в запросе просто используется :id, то по умолчанию используется тип String). Использование плейсхолдеров упрощает построение запросов, а главное исключает возможность написания небезопасных SQL-запросов, подверженных SQL-инъекциям.
    
    Использование плейсхолдеров не является обязательным, однако в случае отказа от них разработчик должен самостоятельно позаботиться о подстановке данных в запрос. Здесь может быть полезным метод модели escape, который экранирует строки (при использовании СУБД MySQL его работа аналогична 
    • 0
      ITFrogs ITFrogs 12 августа 2016 18:15 #

      Кстати, всегда хотел спросить какой тип данных в mysql отвечает за

      'b'  Boolean

      Я грешным делом всегда применяю tinyint и пользуюсь 0 и 1. Да и в вебасистовских таблицах ни разу не встречал boolean

      • +2
        Сергей Сыроежкин Сергей Сыроежкин 12 августа 2016 18:17 #

        зачем вам это знание? у вас лучше получается шутить...

        • 0
          ITFrogs ITFrogs 12 августа 2016 19:09 #

          Ну я подшучу над кем-нибудь. Напишу что-то типа WHERE p.active = b:active :)

      • +1
        Genasyst Genasyst 12 августа 2016 18:24 #

        В MYSQL нет типа boolean! А Вебасист назвал чтобы не путать прогеров!

      • +2
        Syrnik.com Syrnik.com 12 августа 2016 20:50 #

        Ну ORM-то нет в WA-фреймворке. Но адаптер бд, по идее, должен смаппить это на int 1/0

        то есть заведи, например, поле active INT(1) default=0 и попробуй использовать ->where('acive=b:active', array('active'=>true))

        • 0
          ITFrogs ITFrogs 12 августа 2016 21:13 #

          В крутой кабак заходит мужик и говорит бармену:
          — Мне 100 грамм водки.
          Бармен наливает, подает. Мужик достает из кармана мензурку и удостоверение:
          — Контрольная закупка. 75 грамм! Штраф $50.
          Следующий вечер. Те же лица. Мужик снова измеряет мензуркой и снимает полтинник штрафа. Потом спрашивает бармена:
          — Слушай, ты же меня узнал, почему все равно недолил?
          — Да мне проще полтинник отдать, чем руку сбивать из-за тебя...

Добавить ответ

Чтобы добавить комментарий, зарегистрируйтесь или войдите