2012-06-15 28 views
12

Tôi đã gắn thẻ bài đăng này là WordPress, nhưng tôi không hoàn toàn chắc chắn là WordPress cụ thể, vì vậy tôi đăng nó lên StackOverflow thay vì WPSE. Giải pháp không nhất thiết phải là WordPress cụ thể, chỉ cần PHP.Tôi làm cách nào để tạo bộ lọc nội dung hiệu quả cho một số bài đăng nhất định?

Các Kịch bản
tôi chạy một fishkeeping website với một số loài cá nhiệt đới Species ProfilesGlossary mục.

Trang web của chúng tôi được định hướng quanh hồ sơ của chúng tôi. Họ là, như bạn có thể hạn nó, bánh mì và bơ của trang web. Những gì tôi hy vọng đạt được là, trong mỗi hồ sơ loài đề cập đến một loài khác hoặc một mục chú giải thuật ngữ, tôi có thể thay thế những từ đó bằng một liên kết - chẳng hạn như bạn sẽ thấy here. Lý tưởng nhất, tôi cũng muốn điều này xảy ra trong tin tức, bài viết và bài viết trên blog.

Chúng tôi có gần 1400 species profiles1700 glossary entries. Hồ sơ loài của chúng tôi thường dài và cuối cùng đếm hồ sơ loài của chúng tôi một mình numbered more than 1.7 million words thông tin.

Những gì tôi đang Hiện nay Cố
Hiện nay, tôi có một filter.php với một chức năng mà - Tôi tin rằng - không những gì tôi cần nó để làm. Mã này khá dài và có thể được tìm thấy trong đầy đủ here.

Bên cạnh đó, trong theme WordPress của tôi functions.php, tôi đã điều sau đây:

# ============================================================================================== 
# [Filter] 
# 
# Every hour, using WP_Cron, `my_updated_posts` is checked. If there are new Post IDs in there, 
# it will run a filter on all of the post's content. The filter will search for Glossary terms 
# and scientific species names. If found, it will replace those names with links including a 
# pop-up. 

    include "filter.php"; 

# ============================================================================================== 
# When saving a post (new or edited), check to make sure it isn't a revision then add its ID 
# to `my_updated_posts`. 

    add_action('save_post', 'my_set_content_filter'); 
    function my_set_content_filter($post_id) { 
     if (!wp_is_post_revision($post_id)) { 

      $post_type = get_post_type($post_id); 

      if ($post_type == "species" || ($post_type == "post" && in_category("articles", $post_id)) || ($post_type == "post" && in_category("blogs", $post_id))) { 
       //get the previous value 
       $ids = get_option('my_updated_posts'); 

       //add new value if necessary 
       if(!in_array($post_id, $ids)) { 
        $ids[] = $post_id; 
        update_option('my_updated_posts', $ids); 
       } 
      } 
     } 
    } 

# ============================================================================================== 
# Add the filter to WP_Cron. 

    add_action('my_filter_posts_content', 'my_filter_content'); 
    if(!wp_next_scheduled('my_filter_posts_content')) { 
     wp_schedule_event(time(), 'hourly', 'my_filter_posts_content'); 
    } 

# ============================================================================================== 
# Run the filter. 

    function my_filter_content() { 
     //check to see if posts need to be parsed 
     if (!get_option('my_updated_posts')) 
      return false; 

     //parse posts 
     $ids = get_option('my_updated_posts'); 

     update_option('error_check', $ids); 

     foreach($ids as $v) { 
      if (get_post_status($v) == 'publish') 
       run_filter($v); 

      update_option('error_check', "filter has run at least once"); 
     } 

     //make sure no values have been added while loop was running 
     $id_recheck = get_option('my_updated_posts'); 
     my_close_out_filter($ids, $id_recheck); 

     //once all options, including any added during the running of what could be a long cronjob are done, remove the value and close out 
     delete_option('my_updated_posts'); 
     update_option('error_check', 'working m8'); 
     return true; 
    } 

# ============================================================================================== 
# A "difference" function to make sure no new posts have been added to `my_updated_posts` whilst 
# the potentially time-consuming filter was running. 

    function my_close_out_filter($beginning_array, $end_array) { 
     $diff = array_diff($beginning_array, $end_array); 
     if(!empty ($diff)) { 
      foreach($diff as $v) { 
       run_filter($v); 
      } 
     } 
     my_close_out_filter($end_array, get_option('my_updated_posts')); 
    } 

Cách làm việc này, như (hy vọng) được mô tả bởi các comment của mã, là mỗi giờ WordPress hoạt động một công việc định kỳ (giống như một cron giả - hoạt động khi người dùng truy cập, nhưng điều đó không thực sự quan trọng vì thời gian không quan trọng) chạy bộ lọc được tìm thấy ở trên.

Lý do đằng sau việc chạy nó hàng giờ là nếu chúng tôi cố chạy nó khi mỗi bài đăng được lưu, nó sẽ gây thiệt hại cho tác giả. Một khi chúng tôi nhận được các tác giả khách tham gia, đó rõ ràng là không phải là một cách chấp nhận được đi về nó.

Vấn đề ...
Trong nhiều tháng, bây giờ tôi đã gặp vấn đề nhận được bộ lọc này chạy cách đáng tin cậy. Tôi không tin rằng vấn đề nằm ở chính bộ lọc, nhưng với một trong các chức năng cho phép bộ lọc - tức là công việc cron, hoặc chức năng chọn bài viết nào được lọc, hoặc chức năng chuẩn bị danh sách từ vv. Bộ lọc.

Thật không may, chẩn đoán vấn đề là khá khó khăn (mà tôi có thể nhìn thấy), nhờ vào nó chạy trong nền và chỉ trên cơ sở hàng giờ. Tôi đã cố gắng sử dụng chức năng 'update_option' WordPress (về cơ bản viết một giá trị cơ sở dữ liệu đơn giản) để kiểm tra lỗi, nhưng tôi không có nhiều may mắn - và thành thật mà nói, tôi khá bối rối về vấn đề nằm ở đâu .

Chúng tôi đã kết thúc việc đưa trang web hoạt động mà không có bộ lọc này hoạt động chính xác. Đôi khi nó có vẻ làm việc, đôi khi nó không. Kết quả là, hiện tại chúng tôi có một vài hồ sơ loài không được lọc chính xác.

Điều tôi muốn ...
Tôi đang tìm kiếm lời khuyên về cách tốt nhất để chạy bộ lọc này.

Cron có phải là câu trả lời không? Tôi có thể thiết lập một tệp .php chạy mỗi ngày, điều đó sẽ không thành vấn đề. Làm cách nào để xác định bài đăng nào cần được lọc? Nó sẽ có tác động gì đối với máy chủ tại thời điểm nó chạy?

Ngoài ra, trang quản trị WordPress có phải là câu trả lời không? Nếu tôi biết làm thế nào để làm điều đó, một cái gì đó dọc theo dòng của một trang - sử dụng AJAX - cho phép tôi chọn các bài viết để chạy bộ lọc trên sẽ là hoàn hảo. Có một plugin gọi là AJAX Regenerate Thumbnails hoạt động như thế này, có lẽ đó sẽ là hiệu quả nhất?

cân nhắc

  • Kích thước của cơ sở dữ liệu/thông tin bị ảnh hưởng/đọc/viết
  • Những bài viết được lọc
  • Tác động bộ lọc có trên máy chủ; đặc biệt là xem xét tôi dường như không thể tăng giới hạn bộ nhớ WordPress qua 32Mb.
  • Bộ lọc thực tế có hiệu quả, hiệu quả và đáng tin cậy không?

Đây là một câu hỏi khá phức tạp và tôi đã chắc chắn (như tôi đã bị phân tâm khoảng 18 lần bởi các đồng nghiệp trong quá trình này) bỏ qua một số chi tiết. Xin vui lòng thăm dò tôi để biết thêm thông tin.

Xin cảm ơn trước,

+0

Bạn có quyền truy cập vào cơ sở dữ liệu SQL của mình từ ngoại vi không? Nếu bạn lo ngại về cron đang chạy trên máy chủ của mình, bạn có thể chạy tập lệnh ban đầu đã xử lý 1,5 triệu từ của bạn từ một máy tính chạy tập lệnh PHP CLI được kết nối với db của bạn. –

+0

Hơi không liên quan: Trong khi thu hút xung quanh trang web của bạn, tôi nhận thấy rằng cấu trúc url của bạn được viết lại độc đáo. Tuy nhiên, tôi không thể không chú ý rằng các liên kết phân loại đều ở dạng '/ phân loại /% s' mặc dù là cho một đơn đặt hàng hoặc gia đình. Điều này có chủ ý không? Nó có vẻ như '/ phân loại/gia đình /% s' và'/phân loại/thứ tự /% s' sẽ ít mơ hồ hơn. –

+0

Cảm ơn bạn đã có PhpMyCoder, tôi sẽ thêm nó vào danh sách (bao giờ phát triển) :) Tôi hiện không cho phép kết nối từ xa tới cơ sở dữ liệu MySQL của mình, nhưng tôi có thể tạm thời cho phép nó chạy script từ cài đặt wamp. Nó sẽ có nhiều tác động trên trang web nếu cơ sở dữ liệu được viết liên tục trong một khoảng thời gian? – dunc

Trả lời

5

Làm khi hồ sơ được tạo.

Hãy thử đảo ngược toàn bộ quá trình. Thay vì kiểm tra nội dung cho các từ, hãy kiểm tra các từ cho các từ của nội dung.

  1. Phá vỡ các bài nội dung trên nhập cảnh vào chữ (trên không gian)
  2. Loại bỏ trùng lặp, những người dưới kích thước nhỏ nhất của một từ trong cơ sở dữ liệu, những người trên quy mô lớn nhất, và những người thân trong một 'từ thông dụng' danh sách mà bạn giữ.
  3. Kiểm tra từng bảng, nếu một số bảng của bạn bao gồm cụm từ có dấu cách, thực hiện tìm kiếm% text%, nếu không thực hiện kết hợp thẳng (nhanh hơn nhiều) hoặc thậm chí tạo bảng băm nếu thực sự là vấn đề lớn. (Tôi sẽ làm điều này như một mảng PHP và lưu trữ kết quả bằng cách nào đó, không có ý nghĩa sáng tạo lại bánh xe)
  4. Tạo liên kết của bạn với các danh sách nhỏ hơn đáng kể.

Bạn sẽ có thể dễ dàng giữ điều này trong vòng 1 giây ngay cả khi bạn chuyển tới thậm chí 100.000 từ bạn đang kiểm tra. Tôi đã thực hiện chính xác điều này, không có bộ nhớ đệm từ danh sách, cho một bộ lọc Bayesian trước.

Với danh sách nhỏ hơn, ngay cả khi nó tham lam và tập hợp các từ không khớp với "chú hề" sẽ bắt "chú hề", danh sách nhỏ hơn sẽ chỉ là vài từ đến vài chục từ có liên kết. Mà sẽ không mất thời gian để làm một tìm kiếm và thay thế trên một đoạn văn bản.

Ở trên không thực sự giải quyết mối quan tâm của bạn đối với các cấu hình cũ hơn.Bạn không nói chính xác có bao nhiêu, chỉ có rất nhiều văn bản và rằng nó là trên 1400 đến 3100 (cả hai mặt hàng) đặt lại với nhau. Nội dung cũ hơn này bạn có thể làm dựa trên mức độ phổ biến nếu bạn có thông tin. Hoặc vào ngày đã nhập, mới nhất trước tiên. Bất kể cách tốt nhất để làm điều này là viết một kịch bản tạm dừng giới hạn thời gian trên PHP và chỉ chạy hàng loạt một quá trình tải/xử lý/lưu trên tất cả các bài đăng. Nếu mỗi người mất khoảng 1 giây (có lẽ ít hơn nhiều nhưng trường hợp xấu nhất) bạn đang nói 3100 giây đó là một chút ít hơn một giờ.

+0

Bài đăng tuyệt vời, +1. Tôi đã cố gắng để thực hiện giải pháp của bạn sáng nay nhưng gặp phải một vấn đề mà tôi nghi ngờ có thể làm chậm mọi thứ xuống. Một số thuật ngữ mà tôi sẽ tìm kiếm bao gồm 'P. denisonii' và 'S. daemon' - tên loài viết tắt. Như vậy, 'explode' by' "" 'sẽ không hoạt động. Bạn có thể giới thiệu một giải pháp thay thế không? Tôi không thể tưởng tượng rằng việc tìm kiếm từng trường (tức là 'phân phối',' môi trường sống') cho tất cả các cụm từ tìm kiếm sẽ có hiệu quả? – dunc

+0

Nếu không có biểu mẫu viết tắt trong cơ sở dữ liệu, tôi không biết rằng bạn có thể phát hiện các phiên bản viết tắt. Cụ thể, nếu trong cơ sở dữ liệu bạn có "Clown Loach" nhưng trong văn bản bạn có "C. Loach", tôi không thấy cách nào để xử lý hiệu quả trừ khi bạn có một trường trong cơ sở dữ liệu (cho các loài) các phiên bản tên ngắn. Nhưng nếu bạn lo lắng vì "C." dường như có vấn đề, hãy nhớ rằng bạn đang tung ra các từ dưới một ngưỡng độ dài và "% Loach%" trong tìm kiếm LIKE sẽ khớp với "Clown Loach" có thể có "C. Loach" trong trường ngắn, do đó bạn sẽ nhận được trận đấu. – DampeS8N

+0

Hmm, tự hỏi nếu tôi sẽ phải quay lại bảng vẽ. Loài cá đều có một trong hai định dạng: 'Satanoperca daemon' hoặc 'S. daemon', trong đó - nếu tôi diễn giải chính xác bạn - sẽ khó khăn/không thể chạy ý tưởng của bạn một cách hiệu quả? – dunc

Các vấn đề liên quan