и снова у меня проблемы с фильтрацией чисел

Добрый вечер.
Вроде бы уже не раз набивал на этом месте шишки, но видимо не достаточно)
Есть сниппет msProducts.
У него есть параметр
optionFilters Фильтры по опциям товаров. Передаются JSON строкой, например, {"optionkey:>":10}
Есть опция, называется m2, тип число, значение у товара = 1000
Вызов сниппета, с попыткой отфильтровать товары у которых m2 > 600 ничего не выводит, поскольку сравнение значение происходит не как число, а как строка и 600 становится больше 1000.
$result =  $modx->runSnippet('msProducts',[
    'parents'=>0,
    'optionFilters'=>'{"m2:>":600}',
    'tpl'=>'@INLINE <p>[[+pagetitle]]</p>',
    'showLog'=>1
]);
Часть SQL запроса в котором видно, что 600 передается как строка в кавычках
WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `Data`.`price` > '0' AND `m2`.`value` > '600' )
Я уже задавал подобный вопрос и мне любезно подсказали, что нужно смотреть в сторону sql метода CAST() для приведения строки к числу.
modx.pro/help/22471
Тогда я решил задачу другим способом, но сейчас решил все -таки попробовать CAST и честно говоря совсем не получилось.
Вот у Ильи
ilyaut.ru/cheats/sorting-on-tv-number-for-pdoresources/
есть пример
{'pdoResources' | snippet : [
  'tpl' => '@INLINE {$pagetitle} - {$price}',
  'sortby' => '{"CAST(`TVprice`.`value` AS DECIMAL(13,3))":"ASC"}',
  'includeTVs' => 'price'
]}
где в сортировке применяется CAST
Пробую у себя
'optionFilters'=>'{"CAST(`m2`.`value` AS DECIMAL(10,0)):>":600}',
Получаю ошибку sql
check the manual that corresponds to your MySQL server version for the right syntax to use near 'm2`.`value` AS DECIMAL(10,0))`.product_id = Data.id AND `CAST(`m2`.`value` AS DE' at line 1
ок, наверное .value для опции лишние.

'optionFilters'=>'{"CAST(`m2` AS DECIMAL(10,0)):>":600}',
Получаю снова ошибку
check the manual that corresponds to your MySQL server version for the right syntax to use near 'm2` AS DECIMAL(10,0))`.product_id = Data.id AND `CAST(`m2` AS DECIMAL(10,0))`.ke' at line 1
Обратные кавычки в таком синтаксисе у меня вызывают всегда ошибку. Убираем кавычки
'optionFilters'=>'{"CAST(m2 AS DECIMAL(10,0)):>":600}',
Ошибка SQL уходит, но значение все равно интерпретируется как строка и правильная выборка не происходит.
Кусок SQL запроса
0.0001080: Added where condition: class_key=msProduct, Data.price:>=0, CAST(m2 AS DECIMAL(10,0)).value:>=600
WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `Data`.`price` > '0' AND `CAST(m2 AS DECIMAL(10,0))`.`value` > '600' )
видно что по прежнему 600 взято в кавычки.

Хотя вот тут Василий говорит, что pdoTools умеет правильно интерпретировать тип данных в выборках
modx.pro/help/3055#comment-24791
а msProducts работает на pdoTools
Но похоже что это работает только для сортировки, а не для фильтрации.
github.com/modx-pro/pdoTools/blob/de109c4e67cd237108680cc9c3d5cc859cfc47df/core/components/pdotools/model/pdotools/pdofetch.class.php#L414-L420

В общем буду благодарен за идеи, как должен выглядеть json для параметра optionFilters чтобы фильтрация сравнила данные как числа, а не как строки.
Александр Мельник
31 марта 2022, 19:41
modx.pro
532
0

Комментарии: 5

vectorserver
05 апреля 2022, 13:08
0
У опции m2 точно тип поля int?

Попробуй вот так:
'optionFilters'=>'{"CAST(m2 AS UNSIGNED INTEGER):>":600}'
    infokirov
    15 ноября 2022, 14:27
    0
    Александр, получилось ли пофиксить данную проблему, или решить ее по другому?
      Александр Мельник
      15 ноября 2022, 19:57
      0
      Удалось, это факт, но честно говоря, как именно удалось, я уже не помню.
      Мне кажется я тогда просто отказался от сниппета msProducts и написал свой, где писал свои запросы в базу и там уже удалось использовать процедуру CAST() чтобы получать строку как число.
      infokirov
      16 ноября 2022, 08:18
      0
      для целых решил задачу так:
      '{ "weight:IN": [5,6,7,8,9] }';
      массив сгенерировать не сложно, но опять проблема возникает, если weight принимает не целое значение, тогда в выборку не попадёт.
        Ivan
        22 июня 2023, 11:19
        0
        Можно через where и innerJoin вот так:
        &innerJoin=`{ "Options":{ "class":"msProductOption"}}`
        &where=`["Options.key = 'm2' AND Options.value > 600"]`
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          5