Поиск по произвольным полям.

В версии плагина 3.x — добавилось много новых вариантов организовать поиск и сортировку объявлений. Коротко о новых возможностях:

  • поиск простой: равенство перемененная = значение*
  • поиск с условием: больше, меньше, больше или равно, меньше или равно, не равно.
  • поиск по интервалу: например переменная должна быть от 4 и до 23 MySQL оператор BETWEEN
  • поиск по заданному множеству: IN
  • и долго думал, но все таки добавил поиск подстроки в тексте регулярным выражением rlike
  • сортировка результата (туда\обратно) простая и сортировка с конвертацией значения в число CAST($sqlNameVar AS SIGNED)

Я рассчитываю на аудиторию, которая уже понимает как работают выше перечисленные операторы, объяснять основы SQL здесь я не буду.
Прежде чем начинать начинать работать с поиском его надо включить в админке плагина есть галочка. В качестве рабочих примеров я буду использовать свой новый проект каталог ссылок он очень показателен так как задействует практически все возможности плагина, здесь много полей данных и собственно говоря новая версия была написана специально для него.

Поиск можно осуществлять либо через GET запрос, то есть сформировать соответствующий URL (ссылку), либо по средствам POST отправив данные через форму поиска.
Простейший пример:
http://loadmen.ru/?ads_quality=HDRip
Найти записи в которых ads_quality (качество видео) равно HDRip.
Однако след пример сработает не совсем так как вы ожидаете:
http://loadmen.ru/?ads_quality=rip
В результате найдутся все записи в которых есть вхождение rip причем регистр не учитывается, это есть не что иное как SQL оператор LIKE причем выражение взято в проценты вот так — $sqlNameVar LIKE ‘%$value%’. В предыдущих версиях плагина я решил, что от простого знака равно толку мало и поставил LIKE, ну так оно и осталось пока — жалоб не поступало, и практика показала, что так намного функциональные. Теперь, когда мы знаем про оператор LIKE давайте найдем все фильмы с 6 канальным звуком (6 ch), для звуковых параметров у нас выделено спец метаполе ads_audio получаем:
http://loadmen.ru/?ads_audio=6 ch SQL: ads_audio.meta_value LIKE ‘%6 ch%’
По открывайте полученные записи и проверьте — везде в поле Аудио будет присутствовать подстрока 6 ch.

Перейдем к условиям. Найдем все фильмы в которых IMDb рейтинг больше 8
http://loadmen.ru/?ads_imdb_rating[more]=8
SQL: ads_imdb_rating.meta_value > 8
Поскольку http протокол плохо переносит, когда в URL всякие значки типа < > = пришлось заменить их на спец слова, такой вот финт ушами :). Общий принцип построения URL таков:
имя_переменной[оператор]=значение
Привожу таблицу соответствия этих слов и операторов SQL:

more > (больше)
less < (меньше)
moe >= (больше или равно)
loe <= (меньше или равно)
ne ( не равно )
between BETWEEN (проверка диапазона)
in IN (принадлежность к множеству)
rlike rlike (регулярные выражения)

Пример с between зададим условие — найти фильмы продолжительность которых от менее 1 часа. Поскольку продолжительность хранится в минутах переводим в минуты и составляем URL:
http://loadmen.ru/?ads_duration[between][0]=0&ads_duration[between][1]=60 SQL: adp_ads_duration BETWEEN 0 AND 60
adp_file_size[between][0]=629145600 — так мы задаем нижний предел
adp_file_size[between][1]=786432000 — а так верхний
немного громоздко, но работает. 🙂

Пример с IN (принадлежность к множеству), давайте попробуем найти все фильмы хорошего качества HDRip, DVDRip и BDRip :
http://loadmen.ru/?ads_quality[in][]=HDRip&ads_quality[in][]=DVDRip&ads_quality[in][]=BDRip
SQL: ads_quality.meta_value in (‘HDRip’,’DVDRip’,’BDRip’)

Пример с rlike приводить не буду.

Комбинирование условий

Условия можно комбинировать как угодно:
http://loadmen.ru/?cat=32&ads_quality=DVDRip&adp_file_size[moe]=734003200
Найти фильмы из категории Документальные (id категории = 32), у которых качество = DVDRip и размер больше либо равно 700 MB (700*1024*1024)

Механизм работы:

За обработку поисковых запросов отвечает функция function ads_queryfilter($query) если поиск идет по мета полю (ads_), то к основному запросу присоединяется LEFT JOIN таблица wp_postmeta и так для каждой переменной ads_. Для поля adp_ ничего присоединять не надо так-как они уже находятся в составе таблицы wp_posts

Теперь скажу самое главное — для каждой переменной можно назначить свою пользовательскую функцию, имя функции должно начинаться с названия переменной и суфикса _query. Так для переменной ads_quality можно назначить свою функцию которая должна вернуть правильный SQL текст с условием поиска и обязательное условие в тексте должен первым идти оператор AND:

function ads_quality_query($value){
   .........
   return ' AND '. ваше условие поиска;
}

Лучше примеров пояснений нет — на loadmen.ru сделаем альтернативу оператору between для поиска фильмов размером указным в формате x:y (MB), предварительно надо открыть секрет размер файлов на loadmen.ru сохраняется в байтах значит переводим наши значения в байты x*1024*1024 (нижний предел) и y*1024*1024 = 786432000 (верхний предел):
http://loadmen.ru/?adp_file_size=700:1400
для этого в ads_config.php добавляем следующую функцию:

function adp_file_size_query($var){
	list($x,$y) = explode(':',$var);
	$x = (int)$x*1024*1024;
	$y = (int)$y*1024*1024;
	$sql_where = " AND ( adp_file_size >= $x AND adp_file_size <= $y ) ";

	return $sql_where;
}

Если вы используете мета поле ads_ тогда к переменной надо обращатся как имя_поля.meta_value например : ads_quality.meta_value

Сортировка

Чтобы задать сортировку записей по какому либо полю используйте след синтаксис:
ads_order[ads_name_var]='sort' где
ads_name_var имя поля по которому вы хотите задать сортировку;
sort указание типа сортировки может принимать след значения : asc, desc, iasc, idesc;
Например отсортируем записи по полю ads_quality
http://loadmen.ru/?ads_order[ads_quality]=asc
SQL: ORDER BY ads_quality.meta_value ASC

Как я уже говорил выше, кроме простой сортировки есть сортировка с принудительной конвертацией значений к числу. Дело в том, что в мета полях, если вы записываете число то оно сохраняется как строка т.к. тип столбца строковый, поэтому если в мета поле хранится число то надо использовать вместо asc iasc. Отсортируем фильмы по рейтингу IMDb:
http://loadmen.ru/?ads_order[ads_imdb_rating]=iasc
SQL: CAST(ads_imdb_rating.meta_value AS BINARY) ASC

Ну и напоследок, хочу обратить выше внимание на замечательную функцию worpdpress add_query_arg() при конструировании url ссылок может сильно облегчить вашу задачу.

Рубрика:  мая 18, 2010.
/ » » »


Похожие записи:

26 комментариев на «Поиск по произвольным полям.»

  1. Иван говорит:

    Пытаюсь разобраться с поиском, ошибка всплывает, может подскажите с чем связана?
    Например, такой запрос:

    ?ads_price[between][0]=0&ads_price[between][1]=2000

    и вот что выдает wordpress:

    WordPress database error: [Unknown column ‘wp_posts.ID’ in ‘on clause’]
    SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts LEFT JOIN wp_postmeta ads_price ON (wp_posts.ID = ads_price.post_id) WHERE 1=1 AND wp_posts.ID NOT IN ( SELECT tr.object_id FROM wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id LEFT JOIN wp_postmeta ads_price ON (wp_posts.ID = ads_price.post_id) WHERE tt.taxonomy = ‘category’ AND tt.term_id IN (‘1’) ) AND wp_posts.post_type = ‘post’ AND (wp_posts.post_status = ‘publish’) AND ads_price.meta_key = ‘ads_price’ AND ads_price.meta_value BETWEEN 0 AND 2000 ORDER BY wp_posts.post_date DESC LIMIT 0, 3

  2. admin говорит:

    сегодня проверил поиск и немного поменял примеры в статье, все нормально работает, у вас какой-то слишком сложный запрос с подзапросом наверно неправильно подставляются строки с условиями в основной запрос, но переделывать пока, что лень

  3. anton говорит:

    А как можно выбрать в массив все значения какой нибудь переменной ads_test из постов определенной категории?

  4. admin говорит:

    ну если вы уверенны что правильно спросили то вам надо тогда писать SQL запрос в таблицу SLECT wp_meta WHERE meta_key = ‘ads_test’
    примерно как то так вернет вам все мета поля ads_test, ах да еще категорию надо… — ну это уже посложнее будет это только за пиво.

    ну а если все таки надо получить все записи из категории и где есть метаполе ads_test тогда мона воспользоваться описанным выше методом

  5. Иван говорит:

    Здравствуйте!
    Хочу сделать сортировку по возрастанию по полю ads_price.

    ?ads_order[ads_price]=asc

    В результате этого получаю следующее. Сравниваются первые цифры, если совпадают то сортировка по второму числу: 30 больше 23, 33 больше 32, тут все нормально. Но вот порядок числа вообще никак не учитывается
    скажем получается что 9 больше чем 100, а 1200 получится больше 10000. Может сможете прояснить ситуацию.

  6. admin говорит:

    http://ili.com.ua/wordpress/poisk-po-proizvolnyim-polyam.html — вот тут все прокоментировано
    прочитайте параграф Сортировка
    в вашем случае надо ипользовать преобразованеи строки в число
    поэтому задействуем
    ?ads_order[ads_price]=iasc

  7. Иван говорит:

    Я обратил внимание на это первоначально и пробовал использовать iasc, idesc однако результат получался такой же, что и asc, desс. Ка будто не работает преобразования поля к числу.

  8. admin говорит:

    может MySQL не поддерживает преобразование выполняется через:
    CAST($sqlNameVar AS BINARY) ASC

    я вам посоветую для начала вывести результирующий запрос откройте ads.php

    и найдите функцию ads_queryfilter
    в конце перед return
    распечатайте $query
    print_r($query);

    потом попробуй поиграться с ним прямо в phpMyAdmin
    ну как то так

    или другой вариант используйте не ads_ поля, а adp_ добавьте нужные вам числовые столбцы непосредственно в таблицу wp_posts например adp_price
    сортировка будет работать

  9. Иван говорит:

    Попробовал второй вариант, заработало корректно, спасибо

  10. anton говорит:

    A count можно как-то реализовать?

  11. anton говорит:

    $postCount; как вариант, но что делать если постраничная розбивка?

  12. anton говорит:

    $numposts = $wp_query->found_posts;
    echo $numposts;

  13. anton говорит:

    с сортировкой тоже проблемы, буду пробовать adp_

  14. Ivan говорит:

    Можно прокомментировать условия проверки на NULL isnull и notnull. Если мне нужно отфильтровать только объявления с загруженными фотками, я должен прописать adp_picture[notnull]?

  15. Ivan говорит:

    как можно сделать переменную флаг загрузки файлов, чтобы потом можно было отфильтровать объявления с фото. Сделал, но для того чтобы она приняла правильное значение нужно дважды обновлять объявления, в первый раз загрузятся файлы а во второй сделается проверка. Но это неправильно

  16. admin говорит:

    если включена опция Применить шаблоны постов, то все что нужно сделать это проверить наличие файлов в масиве $post->files[0] — это первый файл будет

  17. admin говорит:

    isnull трансформируется в SQL функцию ISNULL(sqlNameVar)
    а notnull в NOT ISNULL(sqlNameVar) вот собственно и все
    большие сложности и путаница возникает когда sqlNameVar = 0 и нам надо проверить пустое значение или там что-то есть
    в MySQL значение 0 не значить null а вот php считает их равными

  18. admin говорит:

    Как то там я делал через фильтры??? … вспомню напишу

  19. egoroff говорит:

    Поиск работает только если в настройках WP Чтение-На главной странице отображать-Ваши последние записи.
    А что делать если у меня в качестве главной страницы стоит Постоянная страница?

  20. admin говорит:
    function search_template () {
        if(strstr($_SERVER['PHP_SELF'],'search.php')){
            include(TEMPLATEPATH . '/search.php');
    	    exit;
        }
    }
    add_action('template_redirect', 'search_template');
    

    у меня вот так переключается

  21. egoroff говорит:

    прошу пояснить, как это должно работать?
    1. В качестве главной страницы у меня постоянная страница
    2. ЧПУ стоит /%category%/%post_id%/
    3. Поиск по метаполям — разрешен

    делаю поиск например: /?ads_buldyear=1981
    показывает постоянную ссылку и все ((

  22. admin говорит:

    этот код добавляется в functions.php в папке темы
    а для вашего случая тогда будет так

    function search_template () {
        if($_REQUEST['ads_buldyear']){
            include(TEMPLATEPATH . '/search.php');
    	    exit;
        }
    }
    add_action('template_redirect', 'search_template');
    
    

    естественно шаблон search.php должен присутствовать в текущей теме

  23. Shady говорит:

    Столкнулась с проблемой как у edoroff. Имею почти тоже самое
    1. В качестве главной страницы у меня постоянная страница
    2. ЧПУ по умолчанию
    3. Поиск по метаполям – разрешен
    4. В function.php темы добавлен код с $_REQUEST[‘ads_url’]

    делаю поиск например: /?ads_url=610000
    (использую поле url для цены, и конечно редактировала form_templ…. и post_templ… в соответствии, но не думаю, что это могло затронуть queryfilter)
    показывает главную постоянную страницу, но при этом добавляет к ней строку «Результаты поиска:» и метаданные главной страницы, которых нет при обычном построении страницы.

    Убираю с главной страницы постоянную стр., убираю доп.код из function.php — результатов не выдает, лишь меняются строчки с надписами «нет результатов», что заставляет думать, что просто ни одна запись не подпадает под мой запрос. Крутила строку запроса под разными углами — ничего.

    Может в search.php что не так? В основе используется стандартный шаблон последнего WP — twentyten

  24. admin говорит:

    ух проблемы с этим поиском выдаю рабочую версию
    1) создаем в корне сайта! файл search.php с таким кодом

    < ?php
    define('WP_USE_THEMES', true);
    define('WP_SEARCH', true);
    /** Loads the WordPress Environment and Template */
    
    require('./wp-blog-header.php');
    ?>
    

    в function.php темы

    function search_template () {
        if(strstr($_SERVER['PHP_SELF'],'search.php')){
            include(TEMPLATEPATH . '/search.php');
    	    exit;
        }
    
    }
    add_action('template_redirect', 'search_template');
    

    тоесть получается так если в url присутствует search.php значит переключаемся на шаблон поиска который search.php в текущей теме

    теперь url для поиска должен выглядеть
    http://site.com/search.php?ads_url=610000

    или вот так посложнее

    http://asxo.od.ua/search.php?s=&category__and%5B%5D=10&category__and%5B%5D=45&adp_price_total%5Bbetween%5D%5B0%5D=&adp_price_total%5Bbetween%5D%5B1%5D=60000&ads_order%5Badp_price_total%5D=asc

    запсиси должны быть одновременно в категории 10(продажа) и 45 (Одесса)
    верхний предел цены установлен до 60000 и сортировка задана по цене — возрастание

  25. Shady говорит:

    к сожалению и этим методом не сработало. вопрос цены пока не стоит так резко, потому буду решать его чуть позже, а поиск по пересекающимся категориям я решила на основе relevanssi плагина (надстройка над поиском) осталось лишь следить, чтобы названия категорий не попадались в постах, которые не относятся к этим категориям, и в данном проекте это реально.

  26. Александр говорит:

    Здравствуйте! Подскажите пожалуйста где нужно прописать ?ads_order[ads_price]=iasc чтобы сортировка по числу шла?

Добавить комментарий

Новости

  • Власть Киева экономит на школьниках
  • Украина и Польша начнут общий проект
  • Украинцы отдадут за газ всю зарплату
  • В Одессе откроется волонтерский центр
  • Россияне будут въезжать в Украину по загранпаспортам
  • В Харькове укрепляют границы с Россией
  • Планы прекратить транзит газа в Европу
  • Комментарии


    Расширеный поиск +

    Другие статьи

    Объявления

    Мои проекты на WordPress

    Одесса Процессор Недвижимости, - специализированная доска объявлений по недвижимости на стоимость сборки $300 с установкой.
    �льичевск - доска объявлений городская доска объявлений, основные разделы: недвижимость, транспорт, услуги, работа, куплю-продам. Стоимость сборки $300 с установкой.
    HiTech.Expert- все о высоких технологиях - разработка, поддержка.

    Счетчики

    our blog