ComBioLaw.De » Blog » เขียนโปรแกรม » โปรแกรมค้นหาข้อมูลสำหรับ CMS
โปรแกรมค้นหาข้อมูลสำหรับ CMS
มีอยู่ช่วงหนึ่ง BioLawCom ของเราจึงตัดสินใจใช้ Google เป็นเครื่องมือในการหาข้อมูลบนหน้าเวบไซท์ ในระยะแรกใช้ได้ผลดีทีเดียว เพราะช่วงนั้น Google เข้ามาเก็บข้อมูลของพวกเราค่อนข้างเยอะ และบ่อย แต่สองสามอาทิตย์ที่ผ่านมา ผมหาอะไรบน BioLawCom ผ่าน Google ไม่เคยเจอ ส่วนมาก Google จะส่งข้อมูลเก่าเก็บมาให้ ผมจึงเดาว่า Google มีการจัดข้อมูลใหม่ ข้อมูลใหม่ที่เคยเก็บไปหายเกลี้ยง ทำให้ผมรู้สึกว่า การหาข้อมูลบนหน้าเวบไซท์ตัวเองผ่าน Search Engine ยอดนิยม ดีและง่ายก็จริง แต่เราก็ต้องไปอิงกับบริษัทเหล่านี้มากเกินไป วันไหนเขาเลิกสนใจเรา เราก็หาอะไรบนหน้าเวบตัวเองไม่เจอ ผมก็เลยต้องแก้ปัญหา ที่หาทางแก้ไม่ได้มานาน (เพราะดันเขียน CMS ใช้เอง) นั่นคือ เขียนโปรแกรมค้นหาข้อมูลเอง ... |
|
|
โจทย์สำคัญของการเขียนโปรแกรมค้นหาคือ จะใช้เงื่อนไขใดในการเรียงลำดับความสำคัญของข้อมูล ? สำหรับ Search Engine ระดับ Hi-End อย่าง Google หรือ Yahoo ก็จะมีเงื่อนไขต่าง ๆ กันเช่น
1 . ค้นหาโดยใช้ SQL โดยใช้ WHERE และ ORDER BY ยกตัวอย่างเช่น
SELECT id, topic, content FROM content WHERE topic LIKE '%something%' OR content LIKE '%something%' ORDER BY update_timeplain code เป็นวิธีที่ CMS ส่วนมากเลือกใช้ เช่น Wordpress, Joomla ข้อดีคือ ง่าย และ ใช้พลังการประมวลผลของ Server ต่ำ แต่ข้อเสียคือ การเรียงลำดับข้อมูลทำได้ไม่ดี นอกจากนี้ข้อมูลที่อยู่ใน HTML-Tag ยังได้รับการค้นหา เหมือนข้อมูลปกติ ผลที่ได้จึงไม่เป็นที่น่าพอใจ ข้อเสียอีกอย่างของวิธีนี้คือ หากมีข้อมูลที่เก็บไว้หลายตาราง การเรียงลำดับข้อมูลก็จะยุ่งยากไปกันใหญ่ 2. ค้นหาผ่านตาราง Keywords ตัว CMS ต้องสร้างตาราง Keywords ค้นหาว่าหน้าไหนมี Keywords คำว่าอะไรบ้าง จำนวนกี่คำ เมื่อมีการค้นหาข้อมูลเกิดขึ้น โปรแกรมจะเทียบข้อมูลที่ค้นหากับตาราง Keywords เรียงลำดับความสำคัญตามตาราง Keywords แล้วสร้างลิ้งก์ไปยังข้อมูลที่อยู่ในตาราง Keywords วิธีนี้ได้ผลการค้นหาเป็นที่น่าพอใจมาก แต่ปัญหาอยู่ที่การสร้างตาราง Keywords นี่แหละครับ เพราะเราไม่รู้ว่าคำใดควรอยู่ในตารางบ้าง เราควรอัพเดดตารางบ่อยเพียงใด ซึ่งการสร้างตาราง Keywords เป็นเรื่องที่ซับซ้อนและใช้พลังการประมวลผลของ Server ที่สูงมาก Drupal เป็น CMS ตัวหนึ่งครับ ที่ใช้วิธีการดังกล่าว วิธีที่ผมใช้คือ แยกการค้นหาออกเป็นสามระดับตามความสำคัญ ระดับแรกคือค้นหาจากชื่อเรื่อง หากเรื่องใดมีชื่อเรื่องตรงกัคำที่ค้นหา แสดงว่ามีความเป็นไปได้สูง ที่เรื่องนั้นตรงกับความต้องการของการค้นหา ระดับที่สองคือ ค้นหาจาก tags และระดับสุดท้ายคือ ค้นหาจากเนื้อเรื่อง นอกจากนี้ในแต่ระดับยังมีการเรียงลำดับตามเวลาที่แก้ไขข้อมูล อันที่จริงเงื่อนไขนี้ไม่ดีเท่าที่ควร การเรียงลำดับตามจำนวน Keywords เป็นวิธีการที่ดีกว่า แต่ปัญหาก็คือ การจะหาว่า การเรียงลำดับตามจำนวน Keywords ได้นั้น เราต้องเรียกข้อมูลทั้งหมดที่มี Keywords ที่ต้องการออกมาจากฐานข้อมูลก่อน จากนั้นจึงหาว่าข้อมูลชุดใด มีจำนวน Keywords ที่ต้องการหาจำนวนเท่าใด แล้วจึงสามารถเรียงลำดับข้อมูบตามจำนวน Keywords ได้ ซึ่งเป็นวิธีที่ใช้ทรัพยากร Server เยอะมาก แต่การเรียงลำดับตามเวลาการแก้ไขนั้น ทำได้ง่ายโดยผ่านคำสั่ง SQL ซึ่งโปรแกรมการค้นหาข้อมูลที่ว่า หน้าตาประมาณนี้ครับ (ยาวเชียว)
<?php function search($search_tables){ if(strlen($_GET[search])){ $search_perpage = 10; $result_count = 0 ; $begin_page = abs($_GET[page])*abs($search_perpage); $end_page = (1+abs($_GET[page]))*abs($search_perpage); $modes = array('topic', 'tag', 'content'); if(count(split('+',$_GET[search])) > 1){ $plus = true; $words = split('+',$_GET[search]); } else{ $plus = false; $words = split(' ',$_GET[search]); } foreach($modes as $mode){ foreach($search_table as $table){ if(isset($ids[$table[table]])) $id = $ids[$table[table]]; $query = "SELECT id,$table[topic],$table[content] FROM $table[table] "; if ($plus) $logical = 'AND'; else $logical = 'OR '; $where = ''; foreach($words as $wordplus){ $where .= $table[$mode]." LIKE '%$wordplus%' $logical "; } $query .= "WHERE ( ".substr($where,0,-4)." )"; $query .= " $id ORDER BY $table[update] DESC"; $result = db_array($query); foreach($result as $row){ $ids[$table[table]] = $ids[$table[table]].' AND id != '.$row[id]; if($result_count >= $begin_page AND $result_count < $end_page){ $content_result = textsearch($row[$table[content]], $words); if($content_result[0]){ $search_result[] = Array(url => $table[url].'/'.$row[id], topic => $row[$table[topic]], content => "<b>($content_result[0] keywords)</b><br>".$content_result[1]); }else{ $result_count = $result_count-1; } } $result_count = $result_count+1; } unset($result); } } } $title = $lang[search].' : '.$_GET[search].' ('.$result_count.' results )'; do_something_to_render_page($title,$search_result); } function textsearch($text, $searchs){ $text = str_replace("<br />","n",$text); $content_text = strip_tags($text); $content_split = split($searchs[0],$content_text); if(count($content_split) > 1){ $pre_content = split("n",$content_split[0]); $content_result .= $pre_content[count($pre_content)-2].' '; $content_result .= $pre_content[count($pre_content)-1].' '; $content_result .= $searchs[0]; $sub_content = split("n",$content_split[1]); $content_result .= $sub_content[0].' '; $content_result .= $sub_content[1].' '; $content_result = '... '.$content_result.' ...'; foreach($searchs as $search){ $keywords += count(split($search,$content_text)); $content_result = str_replace($search,"<b class="keyword">$search</b>",$content_result); } }else{ $keywords = 0; $content_result .= '' ; } return array($keywords, $content_result); } function db_array($query){ $state = db_query($query); $data = array(); while($row=mysql_fetch_assoc($state)){ $data[]=$row; } return $data; } function db_query($query){ $dbh = mysql_pconnect(DB_HOST,DB_USER,DB_PASS): mysql_select_db(DB_NAME,$dbh); $result = mysql_db_query(DB_NAME,$query,$dbh); return $result; } ?>plain code ในโปรแกรมนี้ประกอบด้วยฟังก์ชันต่าง ๆ 4 ฟังก์ชันคือ
Array( '0' =>Array( 'table' => 'blog', 'topic' => 'topic', 'content' => 'content', 'tag' => 'freetags', 'update' => 'publish_time', 'url' => 'blog'), '1' =>Array( 'table' => 'article', 'topic' => 'topic', 'content' => 'content', 'tag' => 'freetags', 'update' => 'publish_time', 'url' => 'article'), '2' =>Array( 'table' => 'gallery', 'topic' => 'topic', 'content' => 'content', 'tag' => 'freetags', 'update' => 'publish_time', 'url' => 'gallery') )plain code ในตัวอย่างเป็นการตั้งค่าตามโปรแกรม X-BLC หากใครต้องการนำโปรแกรมนี้ไปใช้ ก็ต้องปรับโครงสร้างตัวแปรให้เข้ากับตารางในฐานข้อมูลอีกครั้งหนึ่งครับ โดยในตัวแปร $search_tables เป็น assosiate array ที่มีคีย์หกคีย์ดังนี้ครับ
โปรแกรมนี้เหมาะสำหรับเวบไซท์ขนาดกลางเท่านั้นครับ เงื่อนไขในการเรียงลำดับข้อมูล ยังไม่เพียงพอสำหรับเวบไซท์ที่มีข้อมูลปริมาณมาก สำหรับเวบไซท์ขนาดใหญ่ การเรียงลำดับข้อมูลตามจำนวน Keywords เป็นวิธีที่เหมาะสมที่สุดครับ |
|
16 Mar 07 | by | tags เขียนโปรแกรม Search Search Engine Google CMS PHP SQL X-BLC
bow_der_kleine
คือผมยังไม่เข้าใจ yield ครับพี่ไท้ ขอความกรุณาพี่ไท้อธิบายด้วยครับ :D แต่ขั้นต่อไปที่ผมจะเพิ่มเข้ามา คือ ระบบ cache + incremental search ครับ แต่ตอนนี้ยังแก้ไม่ตกอยู่เหมือนกัน หากสำเร็จก็คงแก้ปัญหาเรื่องเปลืองพลัง CPU ได้ระดับหนึ่งครับ |
การเขียนโปรแกรมค้นหาข้อมูลบนเวบไซท์นั้น เป็นเรื่องที่ยากและซับซ้อนมาก ลำพังเพียงแค่หาข้อมูลให้เจออย่างเดียวนั้น ไม่ยากครับ แต่ศาสตร์และศิลป์ของโปรแกรมค้นหาข้อมูลบนหน้าเวบไซท์นั้น อยู่ที่การจัดลำดับความสำคัญของข้อมูลที่หาเจอมากกว่า นี่เป็นเหตุผลหนึ่ง ที่ทำให้ Google ได้รับความนิยม เพราะการจัดลำดับความสำคัญข้อมูลของ Google ดี ทำให้ผู้ใช้เจอข้อมูลที่ต้องการเร็วขึ้น
พี่ไท้
จากการตรวจสอบโค้ดแล้วพบว่า น่าจะวนหลาย ๆ รอบมากเลยนะครับ ^o^ แบบนี้คงจะกิน CPU ของเครื่อง hosting ที่พวกเราเช่าใช้น่าดู ถ้ามีการแทรกคำสั่งที่สามารถ yield เพื่อคืนเวลาให้กับ CPU ได้ คงจะดีไม่น้อยเลย
21 Mar 07