0

私のサイトには、カトリック百科事典があります。11,000以上の記事があります。

私のサイトの記事の語句をカトリック百科事典の関連項目へのリンクに置き換えることに興味があります。だから、誰かが言うなら:

聖ペテロは最初の教皇でした。

聖ペテロを聖ペテロに関する記事へのリンクに置き換え、教皇を教皇に関する記事へのリンクに置き換える必要があります。

動作していますが、非常に遅いです。30,000 以上の可能な置換があるため、最適化することが重要です。ここからどこへ行けばいいのかわかりません。

これが私の既存のコードです。Drupal を使用していることに注意してください。また、単語を [cathenlink] タグに置き換え、そのタグをコードの後半で実際の HTML リンクに置き換えます。

function ce_execute_filter($text)
{

    // If text is empty, return as-is
    if (!$text) {
        return $text;
    }

    // Split by paragraph
    $lines = preg_split('/\n+/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

    // Contains the parsed and linked text
    $linked_text = '';

    foreach ($lines as $line)
    {

        // If this fragment is only one or more newline characters,
        // Add it to $linked_text and continue without parsing
        if (preg_match('/^\n+$/', $line)) {
            $linked_text .= $line;
            continue;
        }

        // Select any terms that might be in this line
        // Ordered by descending length of term,
        // so that the longest terms get replaced first
        $result = db_query('SELECT title, term FROM {catholic_encyclopedia_terms} ' .
                "WHERE :text LIKE CONCAT('%', CONCAT(term, '%')) " .
                'GROUP BY term ' .
                'ORDER BY char_length(term) DESC',
                array(
                    ':text' => $line
                    ))
            ->fetchAll();

        // Array with lowercase term as key, title of entry as value
        $terms = array();

        // Array of the terms only in descending order of length
        $ordered_terms = array();

        foreach ($result as $r)
        {
            $terms[strtolower($r->term)] = $r->title;
            $ordered_terms[] = preg_quote($r->term);
        }

        // If no terms were returned, add the line and continue without parsing.
        if (empty($ordered_terms)) {
            $linked_text .= $line;
            continue;
        }

        // Do the replace
        // Get the regexp by joining $ordered_terms with |
        $line = preg_replace_callback('/\b('.
                    implode('|', $ordered_terms) .
                    ')\b/i', function ($matches) use($terms)
                {
                if ($matches[1]) {
                return "[cathenlink=" .
                $terms[strtolower($matches[1])] . "]" .
                $matches[1] . "[/cathenlink]";
                }
                },
                $line);

        $linked_text .= $line;
    }

    return $linked_text;
}

単語を 2 回置き換えないように、このように preg_replace を実行しています。私は strtr を使用しますが、単語の一部ではなく完全な単語であることを確認する方法はありません。

これを速くする方法はありますか?現在、かなり遅いです。

4

3 に答える 3

0

Lucene などのインデックス システムを使用して、カトリック百科事典のインデックスを作成できます。頻繁に変更されるとは思わないので、インデックスは毎日更新できます。Lucene は Java で書かれていますが、Zend にはインデックスを読み取ることができる PHP モジュールがあることがわかっています。

于 2013-02-28T11:30:42.290 に答える
0

OK、私がやっている方法がおそらく最も効率的だと思います。私が思いついたのは、投稿を 1 週間に 1 回以上解析する必要がないように、結果を 1 週間キャッシュすることです。このソリューションを実装すると、サイトの速度が著しく向上したため、機能しているようです。

于 2013-02-28T20:56:00.320 に答える
0

LIKEキーワードがあなたを遅くしていると思います。ですかindexed

ここでいくつかの手がかりを見つけることができます

于 2013-02-28T02:05:22.077 に答える