Выборка по Значению TV параметра
Привет всем читателям ModxClub, первым делом пользуясь случаем хочу поздравить и мало-ли кому напомнить о том что наступил новый год ;) В поисках истока решения по поводу выборки ресурсов с критериями по значению их Телевизоров «Дополнительных полей(Template Variables/TV)», не смог найти именно корень этой возможность и в чем она проявляется, а именно сейчас будет кому-как покажется, средней сложности SQL запрос. Раньше ведь мы могли(я мог=D) только взять ресурс и припасти все его TV параметры, но зачем тогда нужна сама таблица modx_site_tmplvar_contentvalues? я недоумевал, да и не было времени у меня чтобы вникнуть в вопрос самостоятельно, ведь разрабы Modx могли обеспечить хранение значений или даже ключей+значений конкретного ресурса через поле modx_site_content.properties которое хранит через xPDO JSON массив. Я припас запрос SQL который может решить задачи посредством вложенных SELECT значений:
для меня была задача поставить запрос таким образом — что-бы запрос был шаблонным и имел любые возможности построения критерий по ключ=значение, точно так-же как и обычная выборка ресурсов с их условиями. SELECT * FROM modx_site_content
LEFT JOIN modx_site_tmplvar_contentvalues
ON modx_site_tmplvar_contentvalues.contentid = modx_site_content.id
WHERE (
modx_site_tmplvar_contentvalues.tmplvarid = (
SELECT modx_site_tmplvars.id FROM modx_site_tmplvars
WHERE modx_site_tmplvars.name='icon'
) AND
modx_site_tmplvar_contentvalues.value = 'example-icon'
)
OR (
modx_site_tmplvar_contentvalues.tmplvarid = (
SELECT modx_site_tmplvars.id FROM modx_site_tmplvars
WHERE modx_site_tmplvars.name='isCosmos'
) AND
modx_site_tmplvar_contentvalues.value = 'IS'
) Главное чтобы код отображался в исходном формате и желательно с подсветкой, а-то подумают что я криворучкиц патцан))))
Код SQL запроса в принципе демонстрирует корень того как можно просто ставить критерии на дополнительные поля при обращении за modResource коллекцией или просто объектом. Первым делом JOINимся в таблицу Значений дополнительных полей LEFT JOIN modx_site_tmplvar_contentvaluesсоответственно сопоставляя ресурс и ссылку с таблицы TV на этот ресурс. ONmodx_site_tmplvar_contentvalues.contentid=modx_site_content.id Далее идет тот самый шаблонный метод становления критерии WHERE ( modx_site_tmplvar_contentvalues.tmplvarid= ( SELECTmodx_site_tmplvars.idFROMmodx_site_tmplvars WHEREmodx_site_tmplvars.name='icon' ) AND modx_site_tmplvar_contentvalues.value = 'example-icon' ) OR ( modx_site_tmplvar_contentvalues.tmplvarid= ( SELECTmodx_site_tmplvars.idFROMmodx_site_tmplvars WHEREmodx_site_tmplvars.name='isCosmos' ) AND modx_site_tmplvar_contentvalues.value = 'IS' ) Разделю это на части, здесь 1 блок в скобках = 1 критерию по полю, опишу блок подробнее: ( modx_site_tmplvar_contentvalues.tmplvarid= ( SELECTmodx_site_tmplvars.idFROMmodx_site_tmplvars WHEREmodx_site_tmplvars.name= <abbr title="icon">{%ИМЯ_TV_ПАРАМЕТРА%}</abbr> ) AND modx_site_tmplvar_contentvalues.value{&ОПЕРАТОР_ВЫРАЖЕНИЯ&} {%ИСКОМОЕ_ЗНАЧЕНИЕ_TV%} ) Далее, после 1ого блока — идет оператор OR — это сопоставимо WHERE условию — WHEREcolumn= 'value' OR ... bla bla where statements UPD1: Оператор AND пока не допустим, я ушел в поиск решения для этой возможности /END_UPD UPD2: Альтернатива более лучший вариант: SELECT * FROMmodx_site_contentASresource WHERE ( resource.idIN ( SELECTval.contentidFROMmodx_site_tmplvarsAStv LEFT JOINmodx_site_tmplvar_contentvaluesASvalONtv.id=val.tmplvarid WHERE ( (tv.name = 'icon' AND val.value = 'example-icon') OR (tv.name = 'isCosmos' AND val.value = 'IS') ) ) ) /END_UPD Еще не думал о оптимизации этого отрывка, просто здесь по логике чем больше критерий по TV — тем больше вложенных SELECT получается, Я пока не знаю как это отразится на производительности Код выдумал буквально только-что) Все это дело я еще не впихивал в xPDO реалии, но как многие знают в нем есть возможность подготовки критерии из нативного SQL, Я мог бы и растянуть статью до моментов с использованием из xPDO и тех прелестях которые открываются с помощью этого не мало важного момента, привести много скринов и time-тестов производительности(которых пока не знаю), но сам решил отписаться вкратце, времени есть не много) сегодня мне стукает 20, поэтому новый топик думаю будет приемлимым) UPD: Нашел я все-же решение которое будет выбирать по значениям нескольких TV, кидаю все наброски: /** @sql ver 1 SUPPORT ONLY OR STATEMENT AND JOINING MAIN TABLE TO modx_site_tmplvar_contentvalues **/ SELECT * FROMmodx_site_content LEFT JOINmodx_site_tmplvar_contentvalues ONmodx_site_tmplvar_contentvalues.contentid=modx_site_content.id WHERE ( modx_site_tmplvar_contentvalues.tmplvarid= ( SELECTmodx_site_tmplvars.idFROMmodx_site_tmplvars WHEREmodx_site_tmplvars.name='icon' ) AND modx_site_tmplvar_contentvalues.value = 'example-icon' ) OR ( modx_site_tmplvar_contentvalues.tmplvarid= ( SELECTmodx_site_tmplvars.idFROMmodx_site_tmplvars WHEREmodx_site_tmplvars.name='isCosmos' ) AND modx_site_tmplvar_contentvalues.value` = 'IS'
)
/** SQL ver 2
SUPPORT ONLY OR STATEMENT
***/
SELECT * FROM modx_site_content AS resource
WHERE (
resource.id IN (
SELECT val.contentid FROM modx_site_tmplvars AS tv
INNER JOIN modx_site_tmplvar_contentvalues AS val
ON tv.id = val.tmplvarid
WHERE (
(tv.name = 'icon' AND val.value = 'example-icon')
OR
(tv.name = 'isCosmos' AND val.value = 'IS')
)
)
)
/** SQL ver 3
SUPPORT COMPLETE STATEMENTS
***/
SELECT * FROM modx_site_content AS resource
WHERE (
(
resource.id IN (
SELECT val.contentid FROM modx_site_tmplvars AS tv
INNER JOIN modx_site_tmplvar_contentvalues AS val
ON tv.id = val.tmplvarid
WHERE (tv.name = 'icon' AND val.value = 'example-icon')
)
)
AND
(
resource.id IN (
SELECT val.contentid FROM modx_site_tmplvars AS tv
INNER JOIN modx_site_tmplvar_contentvalues AS val
ON tv.id = val.tmplvarid
WHERE (tv.name = 'isCosmos' AND val.value = 'IS')
)
)
)