Как сделать и сохранить слизнь для названия поста?


Я использую MongoDB/mongoose для хранения записей в блоге со следующей схемой:

PostSchema = mongoose.Schema({
   title: {type: String},
   body: {type: String}
});

Теперь URL-адреса моих сообщений выглядят следующим образом: http://www.example.local/posts/571f78d077b4454bafcfcced

Я хочу, чтобы мои посты содержали слизня следующим образом: http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title

Итак, мои вопросы таковы:

  1. должен ли я генерировать slug один раз и хранить в рамках схемы PostModel или генерировать на каждом показанном посте?
  2. как сгенерировать slug basen на title (Какие существующие модули узлов решают эту задачу) для не ASCII персонажи?
  3. Whick place следует использовать для перенаправления запросов с http://www.example.local/posts/571f78d077b4454bafcfcced на http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title (nodejs, nginx, клиентская сторона).

Спасибо!

EIDT: я также обнаружил, что в базе данных StackOverflow viwer для qoestion с идентификатором 503429 SO хранит незащищенный заголовок. Так значит ли это, что так вычисляет слизень каждый раз, когда запрашивается вопрос?

1 7

1 ответ:

1. Должен ли я генерировать slug один раз и хранить в рамках схемы PostModel или генерировать на каждом показанном посте?

Оба метода допустимы и имеют плюсы:

  • база данных: быстрее, поскольку нам не нужно генерировать ее каждый раз, когда она нам нужна. Слизни генерируются только один раз.
  • on-the-fly: нам не нужно восстанавливать всю таблицу или информацию базы данных, если вы решите изменить свой шаблон / алгоритм (чего следует избегать в любом случае). Меньше места используется в база данных и меньше данных, передаваемых между вашей базой данных и вашим приложением. Не должно занимать слишком много времени, за исключением тех случаев, когда ваш алгоритм для генерации слизней не является эффективным, но в этом случае время генерации не должно быть проблемой.

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

Я лично почти всегда выбираю для хранения slug в базе данных, которые позволяют указать slug для конкретного пост. Возможно, Вам никогда не придется этого делать, но если дело дойдет до вас, вы будете готовы. Например, если для конкретного сообщения сгенерированный слиток будет awesome-post, и вы хотите, чтобы он был best-awesome-post, Вы можете легко сделать это, если слиток хранится в базе данных, в противном случае вам придется настроить свой алгоритм для каждого "особого" случая, который станет кошмаром с несколькими подобными случаями.

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

2. Как создать slug на основе заголовка (какие существующие модули узлов решают эту задачу)для символов, отличных от ASCII?

Как вы сказали, существует несколько модулей узлов для генерации слизней на основе одного или нескольких полей, таких как заголовок, некоторые даже интегрированы с MongoDB / Mongoose, например Мангуст-url-слизни .

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

Что касается ASCII-части вашего вопроса, если вы посмотрите на код mongoose-url-slugs , например, при создании slug они вызывают функциюremoveDiacritics , которая удаляет эти специальные символы и замените их на дружественный к слизнякам эквивалент.

Один из примеров, который я могу привести, который нуждается в особом обращении, чтобы быть правильно обработанным, - это слово " дорога "в немецком языке:"Straße".

Функция будет определить символ "эсцет" (\u00DF) и заменить его с буквой 'S'.

Если вы хотите сделать шаг вперед, вы должны использовать модуль slug, обрабатывающий unicode & utf-8, например slug , который соответствует RFC 3986 относительно единого ресурса Идентификатор (URI).

Он преобразует заголовок типа i ♥ my title в i-love-my-title и т. д.

3. Какое место следует использовать для перенаправления запросов с http://www.example.local/posts/571f78d077b4454bafcfcced на http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title (nodejs, nginx, клиентская часть).

Если вы храните slug в своей базе данных по причинам, которые я описал выше, slug должен быть создан только один раз, а затем сохранен в базе данных. На этом этапе больше не должно происходить регенерации на стороне сервера или клиента.

При отображении ссылок на на стороне клиента, вы всегда будете безопасно использовать слаг, который вы ранее создали, например http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title для отображения ссылки, следующей за шаблоном, который вы хотите.

В случае клиента, использующего url без slug или частичный slug, как http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make, чтобы перенаправить на правильный url с полным slug, переполнение стека по этому конкретному вопросу в хорошем примере, они просто отправляют 301 перенаправление на правильный url.

Переполнение Стека 301

Они имеют дело с этими особыми случаями на сервер, как и должно быть, поскольку ваше приложение на сервере является единственным (если вы сохраняете slug в базе данных), имеющим полномочия по этому вопросу. Ваше приложение знает правильный slug для конкретной записи, поскольку он находится в базе данных, поэтому, если slug не указан или только частично, что легко обнаружить в вашем приложении, вы можете безопасно вызвать 301 перенаправление на правильный URL с правильным slug, например http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title.

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

Например:

res.writeHead(301, { "Location": `http://www.example.local/posts/${postId}/${postSlug}` });

Поскольку подобный контент доступен через несколько URL, вы также должны использовать элемент canonical link для указания "канонического" URL, который должен использоваться поисковыми системами, например, чтобы избежать проблем с дублированием контента.

<link rel="canonical" href="http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title">

Что касается вашего редактирования о Stack Exchange Data Explorer , я думаю, что они опуская поле из результатов, так как это на самом деле не так важно. Согласно комментарию Ника Крейвера, разработчика программного обеспечения и системного администратора для Stack Exchange , они действительно проверяют, соответствует ли слагаемый заголовок, который у них есть в базе данных, тому, который указан в запросе, и если нет, то они перенаправляют.

правка относительно русских символов в URL:

Если вы хотите сохранить русские символы, например, нет проблем, пока вы не отставаете например, с utf-8. Ваш пример ссылки отображает русские символы, но за сценой URL-адрес "закодирован в процентах "или" закодирован в url", вы можете проверить его самостоятельно, щелкнув правой кнопкой мыши по ссылке в вашем браузере, выбрав проверить, и вы увидите, что URL-адрес на самом деле что-то вроде http://ru.stackoverflow.com/questions/456697/genymotion-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-%D0%BF%D1%80%D0%B8-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B8-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0. Ваш браузер знает, что это url-код, и отображает его правильно с русскими символами.

У вас есть, конечно, узел.модули js или даже собственные методы Javascript для url-кодирования любых URL-адресов, которые вы хотеть.

Если вас тоже интересуют SEO и поисковые системы, Google, например: "мы обычно можем идти в ногу с кодированными URL-адресами UTF-8, и мы обычно показываем их пользователям в результатах поиска (но ссылка на ваш сервер с URL-адресами правильно экранирована)", так что никаких проблем.

Большинство модулей "slugifier" удаляют эти символы, поэтому, если вы действительно хотите сохранить их, вам придется использовать что-то более конкретное, например arSlugify :
var ars = require('arslugify');

var title = 'genymotion ошибка при создании виртуального устройства';

var slug = ars(title);

var url = 'www.example.local/posts/571f78d077b4454bafcfcced/' + slug;
var encodedUrl = encodeURIComponent(url);

console.log(url);
// www.example.local/posts/571f78d077b4454bafcfcced/genymotion-ошибка-при-создании-виртуального-устройства
console.log(encodedUrl);
// www.example.local%2Fposts%2F571f78d077b4454bafcfcced%2Fgenymotion-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-%D0%BF%D1%80%D0%B8-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B8-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0