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

Предположим, это длинная статья (скажем, 100 000 слов), и мне нужно написать PHP-файл для отображения 1, 2 или 38 страницы статьи с помощью

display.php?page=38

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

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


person nonopolarity    schedule 31.05.2009    source источник


Ответы (6)


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

CREATE TABLE article_chunks (
    article_id int not null,
    chunk_no int not null,
    body text
}

Затем, когда вы загружаете страницу статьи:

$sql = "select body from article_chunks where article_id = "
    .$article_id." and chunk_no=".$page;

Всякий раз, когда вы хотите изменить логику разделения статей на страницы, вы запускаете скрипт, который собирает все фрагменты вместе и повторно разделяет их:

ОБНОВЛЕНИЕ: Давая совет, я предполагаю, что ваше приложение больше интенсивно читает, чем пишет, а это означает, что статьи читают чаще, чем пишут.

person artemb    schedule 31.05.2009
comment
что, если есть несколько сотен длинных статей, и их повторное разбиение может потребовать остановки сайта на техническое обслуживание... и если в скрипте повторного разбиения есть ошибка, то контент может быть заражен? - person nonopolarity; 01.06.2009
comment
Что ж, если в каком-либо коде, работающем с данными, есть ошибка, содержимое может быть повреждено. Вы можете избежать остановки сайта, запустив и зафиксировав транзакцию сохранения каждой статьи. Но время от времени останавливать сайт на техническое обслуживание — обычное дело. - person artemb; 01.06.2009
comment
Вам не нужно будет останавливать сайт!!, вы можете восстановить статью, пока она находится в сети. Я бы также предложил добавить табличную статью (с article_id в качестве идентификатора/автоинкремента/... и основного текста), это исходный текст, разбитый на куски. В алгоритме я бы установил триггер для обновления текста чанков онлайн... добавить новые чанки, которых не было, и удалить ненужные чанки. - person Osama Al-Maadeed; 01.06.2009

Вы, конечно, можете вывести ровно 500 слов на страницу, но лучше всего будет сделать какие-то разрывы в вашей статье (конец предложения, конец абзаца). Поместите их в местах, где перерыв был бы хорошим. Таким образом, на ваших страницах будет не ровно X слов на каждой, а около или до X, и он не будет разрывать предложения или абзацы. Конечно, при отображении страниц не отображайте эти маркеры разрыва.

person schnaader    schedule 31.05.2009

Вы можете начать с разбиения статьи на массив абзацев с помощью команды разделения: http://www.php.net/split

$array = split("\n",$articleText);
person Travis    schedule 31.05.2009
comment
Итак, как вы решаете, какие абзацы показывать, когда это страница 38? - person nonopolarity; 01.06.2009

Лучше вручную вырезать текст, потому что не стоит оставлять программу, которая определяет, где вырезать. Иногда он будет обрезан сразу после тега h2 и продолжится текстом на следующей странице.

Для этого используется простая структура базы данных:
article(id, title, time, ...)
article_body(id, article_id, page, body, ...)

SQL-запрос:

SELECT a.*, ab.body, ab.page
FROM article a
INNER JOIN article_body ab
    ON ab.article_id = a.id
WHERE a.id = $aricle_id AND ab.page= $page
LIMIT 1;

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

person sasa    schedule 31.05.2009
comment
говорит, что если таких статей несколько сотен, их ручное разбиение может занять слишком много времени. Кроме того, если в следующем месяце будет решено, что на странице будет 300 слов, нельзя снова разделить их вручную. - person nonopolarity; 01.06.2009

Ваша таблица может быть чем-то вроде

CREATE TABLE ArticleText (
  INTEGER artId,
  INTEGER wordNum,
  INTEGER wordId,
  PRIMARY KEY (artId, wordNum),
  FOREIGN KEY (artId) REFERENCES Articles,
  FOREIGN KEY (wordId) REFERENCES Words
)

это, конечно, может быть очень затратным или медленным и т. д., но вам потребуются некоторые измерения, чтобы определить это (поскольку многое зависит от вашего механизма БД). Кстати, надеюсь, понятно, что таблица «Статьи» — это просто таблица с метаданными о статьях с ключом artId, а таблица «Слова» — это таблица всех слов в каждой статье с ключом wordId (попытка сэкономить место, идентифицируя уже известные слова). при вводе артикля, если это возможно...). Одно специальное слово должно быть маркером «конец абзаца», легко идентифицируемым как таковое и отличным от каждого реального слова.

Если вы структурируете свои данные таким образом, вы получаете большую гибкость при извлечении по страницам, а длину страницы можно изменить в одно мгновение, даже запрос за запросом, если хотите. Чтобы получить страницу:

SELECT wordText
FROM  Articles
 JOIN ArticleText USING (artID)
 JOIN Words USING (wordID)
 WHERE wordNum BETWEEN (@pagenum-1)*@pagelength AND @pagenum * @pagelength + @extras
  AND Articles.artID = @articleid

параметры @pagenum, @pagelength, @extras, @articleid должны быть вставлены в подготовленный запрос во время запроса (используйте любой синтаксис, который нравится вашей БД и языку, например :extras или пронумерованные параметры или что-то еще).

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

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

person Alex Martelli    schedule 31.05.2009

Пусть автор сам разделит статью на части.

Писатели знают, как сделать статью интересной и читабельной, разделив ее на логические части, такие как «Часть 1 — Установка», «Часть 2 — Настройка» и т. д. Имхо, делать это с помощью алгоритма — плохое решение.

Вырезание статьи в неположенном месте только раздражает читателя. Не делай этого.

my 2¢

/0
person 0scar    schedule 01.06.2009