如何制作和存储邮件标题的slu??

我使用MongoDB / mongoose来存储具有以下模式的博客文章:

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

现在我的posturl如下所示: http://www.example.local/posts/571f78d077b4454bafcfcced

我想我的post包含slu like如下: http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title

所以我的问题是:

  1. 我应该生成一次slug和存储PostModel架构或每个post上显示?
  2. 如何为标题(现有的节点模块解决这个任务)生成slug basen非ASCII字符?
  3. 我应该使用什么地方将查询从http://www.example.local/posts/571f78d077b4454bafcfccedredirect到http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title (nodejs,nginx,客户端)。

谢谢!

EIDT:我也发现,在StackOverflow数据库viwer的问题与ID 503429 SO存储non slugged标题。 那么这是否意味着SO在每次请求问题时都会计算出slu g?

1.是否应该生成一次slu and并存储在PostModel模式中或在每个post上生成?

两种方法都是有效的,并有优点:

  • 数据库:更快,因为我们不需要每次需要时都生成它。 S are只生成一次。
  • 即时:如果您决定更改模式/algorithm(无论如何应该避免),我们不需要重新生成整个表格或数据库信息。 数据库中使用的空间较less,数据库与应用程序之间的数据传输量较less。 不应该花太长的时间,除非你的algorithm产生slu is不performance,但在这种情况下,世代时间不应该是一个问题。

在这两种情况下,你必须select一个模式,并定义一个algorithm来生成符合你select的模式的slu slu。

我个人几乎总是select在数据库中存储slu which,让你指定一个特定的职位slu slu。 你可能永远不需要这样做,但如果案件出现,你就准备好了。 例如,如果对于一个特定的post,生成的slu would将是awesome-post并且你希望它是best-awesome-post ,但是如果slu is被存储在数据库中,你可以很容易地做到,否则你将不得不调整你的algorithm为每个“特殊”的情况下,这将成为像这样的多个案例的噩梦。

另一点我认为赞成存储它:只要你发布一篇文章,slu is是这篇文章永久链接的一部分,它应该被认为是不可改变的。 如果我可以在这种情况下避免它,我不是一个生成多次不可变数据的巨大粉丝。

2.如何为非ASCII字符生成基于标题(现有节点模块解决此任务)的slug?

就像你说的那样,存在多个节点模块来生成一个或多个字段(如标题)的slu,,有些甚至与mongoose-url-slugs一起整合到MongoDB / Mongoose中。

在大多数slu,中,重音字符将被转换为不重音的字符,所有内容都将转换为小写字母,删除标点符号,空格replace为-例如

关于你的问题的ASCII部分,例如,如果你看一下mongoose -url-slugs的代码,当生成一个slu ,时,他们会调用removeDiacritics函数去除这些特殊字符,并将它们replace为一个slu friendly友好的等效。

我能想到的一个例子是,需要特殊处理才能正确处理的是德语中的“道路”一词:“街道”。

该function将识别Eszett字符( \u00DF )并将其replace为字母's'。

如果你想前进一步,你应该使用一个处理unicode&utf-8的slug模块,例如符合关于统一资源标识符(URI)的RFC 3986的子弹 。

它会把一个标题转换成i-love-my-title等等。

3.我应该使用哪个地方将查询从http://www.example.local/posts/571f78d077b4454bafcfccedredirect到http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title -for http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title (nodejs,nginx,客户端)。

如果您因为我上面发布的原因而在您的数据库中存储slug,那么应该只生成一次slug,然后保存在数据库中。 此时,服务器端或客户端不应再发生再生。

在客户端显示链接时,您总是可以安全地使用以前生成的slug,例如http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title按照你想要的模式显示一个链接。

如果客户端使用的URL不带子弹或部分http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make ,如http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make ,使用全部子弹redirect到正确的URL,堆栈溢出在一个很好的例子中,他们只是发送301redirect到正确的url。

堆栈溢出301

他们正在处理服务器上的这些特殊情况,因为您的服务器上的应用程序是唯一的(如果您保存在数据库中的slu))对这个事情有权威。 你的应用程序知道数据库中的特定文章是否正确,因此如果没有指定slug或者只是部分文章,这很容易在你的应用程序中检测到,你可以安全地触发一个301redirect到正确的URL呃,像http://www.example.local/posts/571f78d077b4454bafcfcced/how-to-make-and-store-slug-for-title

您应该在Node应用程序中处理这些情况(我假设您正在使用Node,就像您在问题中提到的那样),并在需要时redirect到正确的URL。

例如:

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

由于类似的内容可以通过多个URL访问,因此您还应该使用规范链接元素来指定search引擎应该使用的“规范”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的软件开发人员和系统pipe理员Nick Craver的评论 ,他们确实正在检查他们在数据库中具有的段落标题是否与查询中的标题相匹配,如果没有,他们将redirect。

编辑URL中的俄文字符:

如果你想保留俄文字符,例如没问题,只要你跟上utf-8就可以了。 您的链接示例显示俄语字符,但在幕后url是“百分比编码”或“url编码”,您可以通过右键单击浏览器中的链接,select检查,您会看到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编码,并用俄文字符正确显示它。

你当然有Node.js模块,甚至是本地的Javascript方法来URL编码你想要的任何URL。

如果您也想知道search引擎优化和search引擎,例如谷歌:“我们通常可以跟上UTF-8编码的url,我们通常会在我们的search结果中显示给用户(但通过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