【问题标题】:Search for the first 500 letters and excluding html tags?搜索前 500 个字母并排除 html 标签?
【发布时间】:2010-11-08 19:09:07
【问题描述】:

如何搜索前 500 个字符,不包括 html 标签?

下面是我目前想出的,就是搜索出现在文本中的关键字,

    SELECT *
    FROM root_pages

    WHERE root_pages.pg_cat_id = '2'
    AND root_pages.parent_id != root_pages.pg_id
    AND root_pages.pg_hide != '1'
    AND root_pages.pg_url != 'cms'
    AND root_pages.pg_content_1 REGEXP '[[:<:]]".$search."[[:>:]]'
    OR root_pages.pg_content_2 REGEXP '[[:<:]]".$search."[[:>:]]'

ORDER BY root_pages.pg_created DESC

如何在其中添加更多条件 - 前 500 个不包含 html 标记的字母?

如果能只搜索第一段的关键词就完美了——可以吗?

编辑:

感谢大家的帮助!这是我的解决方案:

    # query to search for “whole word match” in SQL only, e.g. when I search for "rid", it should not match "arid", but it should match "a rid".
    # you can use REGEXP and the [[:<:]] and [[:>:]] word-boundary markers:
    $sql = "
    SELECT *
    FROM root_pages

    WHERE root_pages.pg_cat_id = '2'
    AND root_pages.parent_id != root_pages.pg_id
    AND root_pages.pg_hide != '1'
    AND root_pages.pg_url != 'cms'
    AND root_pages.pg_content_1 REGEXP '[[:<:]]".$search."[[:>:]]'
    OR root_pages.pg_content_2 REGEXP '[[:<:]]".$search."[[:>:]]'

    ORDER BY root_pages.pg_created DESC
    ";

    # use the instantiated db connection object from the init.php, to process the query
    $items = $connection -> fetch_all($sql);
    $total_item = $connection -> num_rows($sql);

    if ($total_item > 0)
    {
        foreach($items as $item)
        {
            # get the content
            if(empty($item['pg_content_2'])) $pg_content = strip_tags($item['pg_content_1']);
                else $pg_content = strip_tags($item['pg_content_2']);

            # get the first 500 letters only
            $pg_content = substr($pg_content, 0, 500);

            # get the matches
            if (preg_match("/\b(".$search.")\b/", $pg_content)) 
            {
                $match[] = $pg_content;
            }

        }

        $total_match = count($match);
        //echo $count;
    }

    if($total_match > 0)
    {
        echo '<result message="'.$total_match.' matches found! Please wait while redirecting." search="'.$search.'"/>';
    }
    else
    {
        echo '<error elementid="input" message="Sorry no results are found."/>';
    }

【问题讨论】:

  • 我不能宽恕您提出的解决方案,因为在我看来它效率很低,但是我会问这个:考虑到您只是,是否需要显示在此页面上找到了多少结果重定向?为了使您的代码更高效,请考虑在找到第一个结果后“中断”循环。
  • 是的,页面只会在找到结果时重定向。那么匹配的内容只会显示在新页面上。在找到第一个结果后,我如何“'打破'循环”?谢谢。

标签: php regex mysql full-text-search


【解决方案1】:

这并不像剥离/跳过标签那么简单——您会发现前 500 个字符通常位于 &lt;style&gt;&lt;script&gt;&lt;head&gt; 中。

简单地删除标签也会中断:

separate<br>words

如果你想正确地做到这一点,我建议在文本输出模式下编写 XSLT 样式表,通过在块级元素周围添加空格、删除脚本、&lt;head&gt; 等将 HTML 转换为纯文本。

一个更简单的方法,杀死小猫,是使用一系列正则表达式而不是 XSLT 来预处理 HTML。

将 HTML 转换为可用文本后,将该文本放在数据库的额外列中,并使用它进行搜索。你甚至可以在上面加上FULLTEXT 索引。

【讨论】:

  • 感谢这个想法。以前从未使用过 XSLT - 需要对其进行一些研究!谢谢:-)
  • 没有人记得当你用正则表达式解析 HTML 时死去的小猫:(
【解决方案2】:

为:

如何在其中添加更多条件 - 前 500 个不包含 html 标记的字母?

您不能仅对 MySQL 执行此操作(至少对于在 100% 的情况下都有效的解决方案) - 请参阅 Parsing Html The Cthulhu Way 和此 SO answer 了解更多详细信息。

PHP strip_tagssubstr 将有助于实现您想要的。

【讨论】:

    【解决方案3】:

    如果段落是用p 元素定义的:

    ... REGEXP '<p[^>]*>'".$search."'</p>'
    

    不要忘记为正则表达式特殊字符转义 $search

    【讨论】:

    • 谢谢。那么这个正则表达式发生了什么 - [[:<: regexp>]*>[[:<:>:]]'??谢谢。
    【解决方案4】:

    如果您真的希望能够从 MySQL 执行此操作,我认为最好的(意见)方法是拥有一个包含纯文本版本 pg_content_1(和 pg_content_2)的重复字段。

    这会增加空间和内存开销,但会加快搜索过程中的处理速度。如果您身边有 ORM 库,则可以将事件挂钩到 onSave 并确保纯文本字段自动更新。

    【讨论】:

    • 我喜欢这个主意!唯一的问题是,如果我使用这个解决方案,我必须在我的程序中更改很多东西......但无论如何谢谢:-)
    猜你喜欢
    • 2011-11-15
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多