从帖子内容中的CPT搜索值的最有效方法

时间:2012-02-08 作者:turbonerd

我有一个词汇表CPT。标题、编辑器、slug和特色图片。

我想在帖子内容(以及我的其他CPT“物种”的内容)中添加一个过滤器,该过滤器将查看每篇帖子中的所有内容,并用指向词汇表条目的链接替换词汇表中的任何单词。

例如

词汇表条目:测试

帖子内容:<p>This is a test post to explain what I mean.</p>

筛选后的结果:<p>This is a <a href="/glossary/t/test/">test</a> post to explain what I mean.</p>.

然而,在任何给定的时间,可能有多达2000个词汇表条目,因此我担心效率。

<小时>

EDIT: THIS CODE NEEDS SOME REWORKING!

我已经开始使用代码as suggested by Matthew Boynes.

我对它进行了一些调整,因为我的$wordlist 变量

有关上述错误的更多信息可用here.

function add_glossary_links($content) {
    global $wpdb, $wordlist;
    if ( !$wordlist && !$wordlist = get_option(\'wordlist\') ) {
        mysql_query(\'SET SESSION group_concat_max_len = 100000\');
        $wordlist = $wpdb->get_var(\'SELECT GROUP_CONCAT(DISTINCT post_title SEPARATOR "|") AS list FROM \'.$wpdb->posts.\' WHERE post_status="publish" AND post_type="glossary" AND post_parent>0\');
        add_option(\'wordlist\', $wordlist);
    }

    $wordlist = str_replace(array(" ", "\'", ".", "/"), array("\\s", "\\\'", "\\.", "\\/"), $wordlist);

    $content = preg_replace_callback(
        \'/\\b(\'.$wordlist.\')\\b/i\',
        create_function(
            \'$matches\',
            \'return "<a href=\\"/glossary/" . strtolower(substr($matches[0],0,1) . "/" . $matches[0]) . "/\\">" . $matches[0] . "</a>";\'
        ),
        $content
    );

    return preg_replace(\'/(<[^<]+)<a\\s.*?>(.*?)<\\/a>/si\',\'$1$2\', $content);
}

add_filter( \'the_content\', \'add_glossary_links\' );
上述功能在一定程度上起作用。我现在有两个问题:

函数正在链接所有内容:

[<a href="/glossary///"></a>caption <a href="/glossary///"></a>id="<a href="/glossary///"></a>attachment_542" <a href="/glossary///"></a>align="<a href="/glossary///"></a>alignleft" <a href="/glossary///"></a>width="<a href="/glossary///"></a>125" <a href="/glossary///"></a>caption="<a href="/glossary///"></a>Amazonas <a href="/glossary///"></a>Magazine - <a href="/glossary///"></a>now <a href="/glossary///"></a>in <a href="/glossary///"></a>English!"]<<a href="/glossary///"></a>a <a href="/glossary///"></a>href="<a href="/glossary///"></a>http://<a href="/glossary///"></a>www.<a href="/glossary///"></a>seriouslyfish.<a href="/glossary///"></a>com/<a href="/glossary///"></a>dev/<a href="/glossary///"></a>wp-<a href="/glossary///"></a>content/<a href="/glossary///"></a>uploads/<a href="/glossary///"></a>2011/<a href="/glossary///"></a>12/<a href="/glossary///"></a>Amazonas-<a href="/glossary///"></a>English-<a href="/glossary///"></a>1.<a href="/glossary///"></a>jpg"><<a href="/glossary///"></a>img <a href="/glossary///"></a>class="<a href="/glossary///"></a>size-<a href="/glossary///"></a>thumbnail <a href="/glossary///"></a>wp-<a href="/glossary///"></a>image-<a href="/glossary///"></a>542" <a href="/glossary///"></a>title="<a href="/glossary///"></a>Amazonas <a href="/glossary///"></a>English" <a href="/glossary///"></a>src="<a href="/glossary///"></a>http://<a href="/glossary///"></a>www.<a href="/glossary///"></a>seriouslyfish.<a href="/glossary///"></a>com/<a href="/glossary///"></a>dev/<a href="/glossary///"></a>wp-<a href="/glossary///"></a>content/<a href="/glossary///"></a>uploads/<a href="/glossary///"></a>2011/<a href="/glossary///"></a>12/<a href="/glossary///"></a>Amazonas-<a href="/glossary///"></a>English-<a href="/glossary///"></a>1-<a href="/glossary///"></a>288x381.<a href="/glossary///"></a>jpg" <a href="/glossary///"></a>alt="<a href="/glossary///"></a>Amazonas <a href="/glossary///"></a>English" <a href="/glossary///"></a>width="<a href="/glossary///"></a>125" <a href="/glossary///"></a>height="<a href="/glossary///"></a>165" /></a<a href="/glossary///"></a>>[/caption<a href="/glossary///"></a>] <<a href="/glossary///"></a>p><a href="/glossary///"></a>Edited <a href="/glossary///"></a>by <a href="/glossary///"></a>Hans-<a href="/glossary///"></a>Georg <a href="/glossary///"></a>Evers, <a href="/glossary///"></a>the <a href="/glossary///"></a>magazine &#<a href="/glossary///"></a>8216;<a href="/glossary///"></a>Amazonas&#<a href="/glossary///"></a>8217; <a href="/glossary///"></a>has <a href="/glossary///"></a>been <a href="/glossary///"></a>widely-<a href="/glossary///"></a>regarded <a href="/glossary///"></a>as <a href="/glossary///"></a>among <a href="/glossary///"></a>the <a href="/glossary///"></a>finest <a href="/glossary///"></a>regular <a href="/glossary///"></a>publications <a href="/glossary///"></a>in <a href="/glossary///"></a>the <a href="/glossary///"></a>hobby <a href="/glossary///"></a>since <a href="/glossary///"></a>its <a href="/glossary///"></a>launch <a href="/glossary///"></a>in <a href="/glossary///"></a>2005, <a href="/glossary///"></a>an <a href="/glossary///"></a>impressive <a href="/glossary///"></a>achievment <a href="/glossary///"></a>considering <a href="/glossary///"></a>it&#<a href="/glossary///"></a>8217;<a href="/glossary///"></a>s <a href="/glossary///"></a>only <a href="/glossary///"></a>been <a href="/glossary///"></a>published <a href="/glossary///"></a>in <a href="/glossary///"></a>German <a href="/glossary///"></a>to <a href="/glossary///"></a>date. <a href="/glossary///"></a>The <a href="/glossary///"></a>long-<a href="/glossary///"></a>awaited <a href="/glossary///"></a>English <a href="/glossary///"></a>version <a href="/glossary///"></a>is <a href="/glossary///"></a>just <a href="/glossary///"></a>about <a href="/glossary///"></a>to <a href="/glossary///"></a>launch, <a href="/glossary///"></a>and <a href="/glossary///"></a>we <a href="/glossary///"></a>think <a href="/glossary///"></a>a <a href="/glossary///"></a>subscription <a href="/glossary///"></a>should <a href="/glossary///"></a>be <a href="/glossary///"></a>top <a href="/glossary///"></a>of <a href="/glossary///"></a>any <a href="/glossary///"></a>serious <a href="/glossary///"></a>fishkeeper&#<a href="/glossary///"></a>8217;<a href="/glossary///"></a>s <a href="/glossary///"></a>Xmas <a href="/glossary///"></a>list&#<a href="/glossary///"></a>8230;</p<a href="/glossary///"></a>> <<a href="/glossary///"></a>p><a href="/glossary///"></a>The <a href="/glossary///"></a>magazine <a href="/glossary///"></a>is <a href="/glossary///"></a>published <a href="/glossary///"></a>in <a href="/glossary///"></a>a <a href="/glossary///"></a>bi-<a href="/glossary///"></a>monthly <a href="/glossary///"></a>basis <a href="/glossary///"></a>and <a href="/glossary///"></a>the <a href="/glossary///"></a>English <a href="/glossary///"></a>version <a href="/glossary///"></a>launches <a href="/glossary///"></a>with <a href="/glossary///"></a>the <a href="/glossary///"></a>January/<a href="/glossary///"></a>February <a href="/glossary///"></a>2012 <a href="/glossary///"></a>issue <a href="/glossary///"></a>with <a href="/glossary///"></a>distributors <a href="/glossary///"></a>already <a href="/glossary///"></a>organised <a href="/glossary///"></a>in <a href="/glossary///"></a>the <a href="/glossary///"></a>United <a href="/glossary///"></a>States, <a href="/glossary///"></a>Canada, <a href="/glossary///"></a>the <a href="/glossary///"></a>United <a href="/glossary/k/kingdom/">Kingdom</a>, <a href="/glossary///"></a>South <a href="/glossary///"></a>Africa, <a href="/glossary///"></a>Australia, <a href="/glossary///"></a>and <a href="/glossary///"></a>New <a href="/glossary///"></a>Zealand. <a href="/glossary///"></a>There <a href="/glossary///"></a>are <a href="/glossary///"></a>also <a href="/glossary///"></a>mobile <a href="/glossary///"></a>apps <a href="/glossary///"></a>availablen <a href="/glossary///"></a>which <a href="/glossary///"></a>allow <a href="/glossary///"></a>digital <a href="/glossary///"></a>subscribers <a href="/glossary///"></a>to <a href="/glossary///"></a>read <a href="/glossary///"></a>on <a href="/glossary///"></a>portable <a href="/glossary///"></a>devices.</p<a href="/glossary///"></a>> <<a href="/glossary///"></a>p><a href="/glossary///"></a>It&#<a href="/glossary///"></a>8217;<a href="/glossary///"></a>s <a href="/glossary///"></a>fair <a href="/glossary///"></a>to <a href="/glossary///"></a>say <a href="/glossary///"></a>that <a href="/glossary///"></a>there <a href="/glossary///"></a>currently <a href="/glossary///"></a>exists <a href="/glossary///"></a>no <a href="/glossary///"></a>better <a href="/glossary///"></a>publication <a href="/glossary///"></a>for <a href="/glossary///"></a>dedicated <a href="/glossary///"></a>hobbyists <a href="/glossary///"></a>with <a href="/glossary///"></a>each <a href="/glossary///"></a>issue <a href="/glossary///"></a>featuring <a href="/glossary///"></a>cutting-<a href="/glossary///"></a>edge <a href="/glossary///"></a>articles <a href="/glossary///"></a>on <a href="/glossary///"></a>fishes, <a href="/glossary///"></a>invertebrates, <a href="/glossary/a/aquatic/">aquatic</a> <a href="/glossary///"></a>plants, <a href="/glossary///"></a>field <a href="/glossary///"></a>trips <a href="/glossary///"></a>to <a href="/glossary///"></a>tropical<a href="/glossary///"></a> destinations<a href="/glossary///"></a> plus<a href="/glossary///"></a> the<a href="/glossary///"></a> latest<a href="/glossary///"></a> in<a href="/glossary///"></a> husbandry<a href="/glossary///"></a> and<a href="/glossary///"></a> breeding<a href="/glossary///"></a> breakthroughs<a href="/glossary///"></a> by<a href="/glossary///"></a> expert<a href="/glossary///"></a> aquarists<a href="/glossary///"></a>, all<a href="/glossary///"></a> accompanied<a href="/glossary///"></a> by<a href="/glossary///"></a> excellent<a href="/glossary///"></a> photography<a href="/glossary///"></a> throughout<a href="/glossary///"></a>.</p<a href="/glossary///"></a>> <<a href="/glossary///"></a>p><a href="/glossary///"></a>U.<a href="/glossary///"></a>S. <a href="/glossary///"></a>residents <a href="/glossary///"></a>can <a href="/glossary///"></a>subscribe <a href="/glossary///"></a>to <a href="/glossary///"></a>the <a href="/glossary///"></a>printed <a href="/glossary///"></a>edition <a href="/glossary///"></a>for <a href="/glossary///"></a>just $<a href="/glossary///"></a>29 <a href="/glossary///"></a>USD <a href="/glossary///"></a>per <a href="/glossary///"></a>year, <a href="/glossary///"></a>which <a href="/glossary///"></a>also <a href="/glossary///"></a>includes <a href="/glossary///"></a>a <a href="/glossary///"></a>free <a href="/glossary///"></a>digital <a href="/glossary///"></a>subscription, <a href="/glossary///"></a>with <a href="/glossary///"></a>the <a href="/glossary///"></a>same <a href="/glossary///"></a>offer <a href="/glossary///"></a>available <a href="/glossary///"></a>to <a href="/glossary///"></a>Canadian <a href="/glossary///"></a>readers <a href="/glossary///"></a>for $<a href="/glossary///"></a>41 <a href="/glossary///"></a>USD <a href="/glossary///"></a>or <a href="/glossary///"></a>overseas <a href="/glossary///"></a>subscribers <a href="/glossary///"></a>for $<a href="/glossary///"></a>49 <a href="/glossary///"></a>USD. <a href="/glossary///"></a>Please <a href="/glossary///"></a>see <a href="/glossary///"></a>the <<a href="/glossary///"></a>a <a href="/glossary///"></a>href="<a href="/glossary///"></a>http://<a href="/glossary///"></a>www.<a href="/glossary///"></a>amazonasmagazine.<a href="/glossary///"></a>com/"><a href="/glossary///"></a>Amazonas <a href="/glossary///"></a>website</a<a href="/glossary///"></a>> for<a href="/glossary///"></a> further<a href="/glossary///"></a> information<a href="/glossary///"></a> and<a href="/glossary///"></a> a<a href="/glossary///"></a> sample<a href="/glossary///"></a> digital<a href="/glossary///"></a> issue<a href="/glossary///"></a>!</p<a href="/glossary///"></a>> <<a href="/glossary///"></a>p><a href="/glossary///"></a>Alternatively, <a href="/glossary///"></a>subscribe <a href="/glossary///"></a>directly <a href="/glossary///"></a>to <a href="/glossary///"></a>the <a href="/glossary///"></a>print <a href="/glossary///"></a>version <<a href="/glossary///"></a>a <a href="/glossary///"></a>href="<a href="/glossary///"></a>https://<a href="/glossary///"></a>www.<a href="/glossary///"></a>amazonascustomerservice.<a href="/glossary///"></a>com/<a href="/glossary///"></a>subscribe/<a href="/glossary///"></a>index2.<a href="/glossary///"></a>php"><a href="/glossary///"></a>here</a<a href="/glossary///"></a>> or<a href="/glossary///"></a> digital<a href="/glossary///"></a> version<a href="/glossary///"></a> <<a href="/glossary///"></a>a <a href="/glossary///"></a>href="<a href="/glossary///"></a>https://<a href="/glossary///"></a>www.<a href="/glossary///"></a>amazonascustomerservice.<a href="/glossary///"></a>com/<a href="/glossary///"></a>subscribe/<a href="/glossary///"></a>digital.<a href="/glossary///"></a>php"><a href="/glossary///"></a>here</a<a href="/glossary///"></a>>.</p<a href="/glossary///"></a>>

提前谢谢,

3 个回复
最合适的回答,由SO网友:Matthew Boynes 整理而成

这是一个有趣的项目。我想我可以在一本书中就这一点写一整章(事实上,我实际上是在下面写的)。不管怎样,我胡乱想出了很多方法,下面是我想到的最简单的方法:

function add_glossary_links($content) {
    global $wpdb, $wordlist;
    if ( !$wordlist && !$wordlist = get_option(\'wordlist\') ) {
        mysql_query(\'SET SESSION group_concat_max_len = 100000\');
        $wordlist = $wpdb->get_var(\'SELECT GROUP_CONCAT(DISTINCT word SEPARATOR "|") AS `list` FROM \'.$wpdb->prefix.\'glossary\');
        add_option(\'wordlist\', $wordlist);
    }
    $content = preg_replace_callback(
        \'/\\b(\'.$wordlist.\')\\b/i\',
        create_function(
            \'$matches\',
            \'return "<a href=\\"/glossary/".strtolower(substr($matches[0],0,1)."/".$matches[0])."/\\">".$matches[0]."</a>";\'
        ),
        $content
    );
    return preg_replace(\'/(<[^<]+)<a\\s.*?>(.*?)<\\/a>/si\',\'$1$2\', $content);
}
add_filter( \'the_content\', \'add_glossary_links\' );
讨论假设有一个表前缀\\u词汇表,我们将选择一个以管道分隔的所有记录列表。当我们在帖子中搜索单词时,这将成为正则表达式的一部分。在此之前,我们将为group\\u concat\\u max\\u length设置一个会话变量,默认情况下,该变量将截断为1024个字符。100000个字符可以容纳10000个9个字母的单词(准确地说是1个10个字母的单词),所以如果需要更多的单词,您可以将其增加。

在里面preg_replace_callback, 我们将用锚定标记来替换所有单词实例。根据需要调整HREF。

这可能会导致某些HTML格式错误(例如,在图像alt中用锚定标记包装一个单词),因此下一个preg\\u替换将修复此问题。如果需要,可以执行另一个操作,以确保已包装在锚定标记中的单词不会被包装在另一个锚定标记中。

为了进行性能测试,我构建了一个由1001个5-15个字符长的随机单词组成的词汇表。如果SELECT GROUP_CONCAT... 结果不会以某种方式缓存到整整一秒钟。如您所见,我在这里所做的是将其存储在一个选项中(当然,您希望在更新词汇表时随时更新该选项)。您可以采取任何数量的步骤来提高性能,这只是一个建议。使用apache benchmark进行测试时,我的页面负载平均增加了6.8%(标准差非常大,因此这实际上不是统计上的显著差异,但我离题了),这是一个悬而未决的问题;这是否至关重要完全取决于网站的访问量。尽管如此,如果它获得了大量流量,人们还是希望它能够启用缓存,在这种情况下,差异将完全可以忽略不计。

结论

这是可行的,但如果这6.8%是关键的,你会想重新考虑这个方法。具体来说,您可以考虑使用javascript进行替换。您可以用类似的方式来完成,将单词列表作为JS变量写出来。这样,您的服务器就不必处理搜索处理,您可以让用户的机器完成所有工作。

备选方案

我尝试的另一种方法是在发布或更新帖子时存储索引,这种方法速度明显更快,但需要更多的编码。在这种情况下,我根据帖子中的每个单词搜索字典,并将匹配项存储在索引表中。然后在页面加载时,像上面那样替换帖子中缩短的单词列表,这样我只处理已知匹配的列表,而不是完整的列表(所以,假设5个单词而不是1000个单词)。如果要探索该路线,需要两个表:

CREATE TABLE `wp_glossary` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `word` tinytext,
  `definition` text,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1002 DEFAULT CHARSET=latin1;

CREATE TABLE `wp_posts_glossary` (
  `post_id` int(11) unsigned NOT NULL,
  `glossary_id` int(11) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
您可以在更新后使用以下方法创建索引:

global $wpdb, $post;
$wpdb->query(\'DELETE FROM \'.$wpdb->prefix.\'posts_glossary WHERE post_id=\'.$post->ID);
$sql_regex = rtrim(preg_replace(\'/[\\W\\s]*(\\w+)[\\W\\s]*/\',\'$1|\',$post->post_content),\'|\');
$wpdb->query(\'INSERT INTO \'.$wpdb->prefix.\'posts_glossary (post_id,glossary_id)
    SELECT \'.$post->ID.\',ID FROM \'.$wpdb->prefix.\'glossary WHERE word REGEXP("^\'.$sql_regex.\'$")\';
我用我的1001个单词的词汇表和《白鲸》的2215个单词的第一章来测试索引,平均构建时间约为1.5秒。因此,如果您走这条路,您应该考虑利用wp\\u cron,这样您就不必等到点击“更新”或“发布”后再对其进行索引。

有趣的东西。希望这有帮助!

干杯~

SO网友:boyska

上面的解决方案非常好,性能问题也是正确的。但“缓存”解决方案非常简单,因此您可以轻松完成:https://codex.wordpress.org/Transients_API您应该在很大的时间范围内缓存词汇表术语列表(您可以预期它是不可变的:当您确实需要更新时,请使用delete_transient())

然后可以修改上述脚本(https://wordpress.stackexchange.com/a/42008/12843 )缓存$wordlist

function add_glossary_links($content) {
    global $wpdb;
    $wordlist = get_transient(\'glossary_list\');
    if ( !$wordlist && !$wordlist = get_option(\'wordlist\') ) {
        mysql_query(\'SET SESSION group_concat_max_len = 100000\');
        $wordlist = $wpdb->get_var(\'SELECT GROUP_CONCAT(DISTINCT word SEPARATOR "|") AS `list` FROM \'.$wpdb->prefix.\'glossary\');
        set_transient(\'wordlist\', $wordlist, 60*60*24*2);
    }
    $content = preg_replace_callback( /*continues...*/
这将使mysql查询非常罕见。然而,如果你的单词列表很大,处理过程仍然会有点慢:为了让它更快,使用“标准”wordpress缓存插件,你不会回头看!

SO网友:Ian Dunn

看看Linkify Text 插件。它似乎在做一件非常类似的事情,您只需修改它,将术语表CPT用于术语,而不是内部术语库。

您可以运行像WP Super Cache这样的缓存插件来避免性能问题。

结束

相关推荐

Search options/filters

我正在尝试向侧栏搜索框添加一些复选框选项,similar to this, 用户可以选择是否搜索All Words, Some Word, 或者Entire phrase.我确实在搜索后找到了这个-Wordpress Search Phrases. “句子”选项似乎很有效,但其他选项则不太好。下面的代码是我目前正在处理的,但如果能得到一些帮助使其正常工作,我将不胜感激。非常感谢S(我不想为此使用插件)。<form action=\"<?php bloginfo(\'home\'); ?>