У меня есть эти таблицы, которые могут быть в базе данных MySQL или Postgres:
| ================================================= ============================== | | статьи | | ================================================= ============================== | | Идентификатор | user_id | состояние | название | текст | созданный_ат | обновленный_ат | аннотация | изображение | | == | ======= | ===== | ==================== | ==== | ====== ==== | ========== | ======== | ===== | | 1 | 1 | 5 | L'hopital rule | ... | 2014-12-05 | | ... | ... | | 2 | 2 | 5 | Гауссовская квадратура | ... | 2012-11-13 | 2014-12-05 | ... | ... | | 3 | 2 | 5 | Устранение Гаусса | ... | 2013-07-18 | 2014-03-09 | ... | ... | | 4 | 3 | 5 | Растительная клеточная структура | ... | 2013-09-10 | 2013-12-15 | ... | ... | | 5 | 4 | 5 | Теория игр | ... | 2011-02-15 | 2012-11-30 | ... | ... | | , , , | | ================================================= ============================== | | =========== | | ==================== | | =========== | | tag_groups | | теги | | пользователи | | =========== | | ==================== | | =========== | | Идентификатор | имя | | Идентификатор | id_article | id_tag | | Идентификатор | имя | | == | ======== | | == | ========== | ====== | | == | ======== | | 1 | Математика | | 1 | 1 | 1 | | 1 | Том Тер | | 2 | Исчисление | | 2 | 1 | 2 | | 2 | Май Ник | | 3 | Градиент | | 3 | 2 | 1 | | 3 | Математика Риа | | 4 | Геометрия | | 4 | 3 | 1 | | 4 | Гаусс Ли | | , , , | | , , , | | , , , | | =========== | | ==================== | | =========== |
Дайте нам $query = "th"
, Давай чем будем $like_query = "%th%"
Я хотел бы искать по $like_query
строка в статьях со следующей логикой:
Первыми результатами должны стать статьи, имеющие tag_group.name, совпадающие с $like_query
строка. Вот это были бы статьи с id=1
, id=2
а также id=3
,
Следующими результатами должны стать статьи, соответствующие названию статьи. Так id=5
добавлен.
Затем добавляются статьи, созданные пользователями с соответствующим именем. Итак, статья с id=3
добавлен.
В конце добавляются статьи, соответствующие тексту.
Все статьи должны быть в этом порядке и не должно быть дубликатов.
Я создал следующий код с build_sql
функция в Laravel:
function like($string, $escape_char = '\\') {
return str_replace(
array($escape_char, '_', '%'),
array($escape_char.$escape_char, $escape_char.'_', $escape_char.'%'),
$string
);
}
function wild($string) {
return DB::connection()->getPdo()->quote('%'.like($string).'%');
}
function build_sql($quoted_query) {
return "SELECT DISTINCT
articles.id, articles.user_id, articles.state, articles.title,
articles.image, articles.abstract, articles.text, articles.created_at,
articles.updated_at
FROM (
SELECT articles.*, ord
FROM (
SELECT articles.*, 1 ord
FROM articles
LEFT JOIN tags ON tags.id_article = articles.id
LEFT JOIN tag_groups ON tags.id_tag = tag_groups.id
WHERE articles.state = 5 AND tag_groups.name ILIKE $quoted_query
UNION
SELECT articles.*, 2 ord
FROM articles
WHERE articles.state = 5 AND articles.title ILIKE $quoted_query
UNION
SELECT articles.*, 3 ord
FROM articles
LEFT JOIN users ON users.id = articles.user_id
WHERE articles.state = 5 AND users.name ILIKE $quoted_query
UNION
SELECT articles.*, 4 ord
FROM articles
WHERE articles.state = 5 AND articles.text ILIKE $quoted_query
) articles
ORDER BY ord ASC, articles.updated_at DESC
) articles;
"}
$articles = DB::table((DB::raw($build_sql(wild($_query)))))->distinct();
$maxPages = ceil(count($articles->get()) / 9);
return View::make('index', array(
'articles' => $articles->simplePaginate(9),
'maxPages' => $maxPages,
));
Это не работает, и я не знаю, что мне делать. Есть ли способ, как написать это красиво, используя красноречивые модели? Или, если нет, как мне обновить строку build_sql?
Задача ещё не решена.
Других решений пока нет …