【问题标题】:How to divide a long article and store in the database for easy retrieval and with paging?长篇文章如何分页存入数据库,方便检索和分页?
【发布时间】:2010-10-30 06:53:47
【问题描述】:

假设是一篇很长的文章(比如 100,000 字),我需要编写一个 PHP 文件来显示文章的第 1、2 或第 38 页,作者:

display.php?page=38

但是每页的字数会随着时间的推移而变化(例如,现在如果是每页 500 字,但下个月,我们可以轻松地将其更改为每页 300 字)。有什么好办法把长篇文章分好存入数据库?

P.S. 如果我们要显示 500 个单词但包含整个段落,则设计可能会更加复杂。也就是说,如果我们已经显示了 480 个单词,但该段落还有 100 个单词,那么即使它超过了 500 个单词的限制,也要显示这 100 个单词。 (然后,下一页不应再显示这 100 个字)。

【问题讨论】:

    标签: php database database-design schema


    【解决方案1】:

    您当然可以每页准确输出 500 个单词,但更好的方法是在您的文章中加入某种中断(句末、段末)。把它们放在适合休息的地方。这样一来,您的页面中的每个单词就不会正好有 X 个单词,而是大约或最多 X 个单词,并且不会将句子或段落分开。 当然,在显示页面时,不要显示这些中断标记。

    【讨论】:

      【解决方案2】:

      您可能希望首先使用 split 命令将文章分成一组段落: http://www.php.net/split

      $array = split("\n",$articleText);
      

      【讨论】:

      • 那么你如何决定在第 38 页时显示哪些段落?
      【解决方案3】:

      我会通过在保存它们时将文章拆分到 chuks 上来做到这一点。保存脚本将使用您设计的任何规则拆分文章,并将每个块保存到如下表中:

      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;
      

      每当您想更改将文章拆分为页面的逻辑时,您都可以运行一个脚本,将所有块拉到一起并重新拆分它们:

      更新:提供建议,我认为您的应用程序是阅读密集型而不是写入密集型,这意味着文章的阅读频率高于撰写频率

      【讨论】:

      • 如果有几百篇长文章,重新拆分它们可能需要停止站点进行维护...并且如果重新拆分脚本中存在错误,那么内容可以被污染了?
      • 好吧,如果任何处理数据的代码中存在错误,内容可能会被损坏。您可以通过围绕保存每篇文章启动和提交事务来避免停止站点。但是偶尔停止站点进行维护是很常见的事情。
      • 您不需要停止站点!!,您可以在文章在线时重建它。我还建议添加一个表格文章(article_id 作为身份/自动增量/...,以及正文),这是分成块的原始文本。在算法中,我会设置一个触发器来在线更新块的文本......添加不存在的新块,并删除不需要的块。
      【解决方案4】:

      手动剪切文本是更好的方法,因为离开一个决定剪切位置的程序不是一个好主意。有时它会在 h2 标签之后被剪切,并在下一页继续显示。

      这是一个简单的数据库结构:
      文章(id,标题,时间,...)
      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 简单地为另一个页面添加新的文本区域...

      【讨论】:

      • 说如果有几百个这样的文章,手动拆分它们可能会花费太长时间。还有,如果决定下个月每页300字,就不能再手动重新拆分了。
      【解决方案5】:

      你的桌子可能是这样的

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

      这当然可能非常占用空间或速度很慢等,但您需要进行一些测量才能确定(很大程度上取决于您的数据库引擎)。顺便说一句,我希望很清楚 Articles 表只是一个包含由 artId 键入的文章的元数据的表,而 Words 表是一个由 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 表,只是每行直接存储的文本)采用这种轻微的变化。

      【讨论】:

        【解决方案6】:

        让作者自己把文章分成几部分。

        作者知道如何通过将文章划分为逻辑部分(例如“第 1 部分 - 安装”、“第 2 部分 - 配置”等)来让文章变得有趣和可读。恕我直言,让算法来做是一个错误的决定。

        在错误的地方砍文章只会让读者生气。不要这样做。

        我的 2 美分

        /0
        

        【讨论】:

          猜你喜欢
          • 2020-07-30
          • 2015-07-03
          • 2021-10-17
          • 1970-01-01
          • 1970-01-01
          • 2011-05-13
          • 1970-01-01
          • 1970-01-01
          • 2017-10-07
          相关资源
          最近更新 更多