دوشنبه ۲۵ اسفند ۱۴۰۴

Monday, March 16, 2026 GMT +3:30

جستجو در مطالب سایت با استفاده از MySQL Full-Text

mysql-fulltext

جستجو در اطلاعات پایگاه داده را می توان جزء اولین و مهمترین نیازهای برنامه های تحت وب برشمرد که تقریبا هر برنامه نویسی در طی تجربه کاری خود با آن مواجه خواهد شد، در MySQL این جستجو از دو طریق میسر است، استفاده از دستور ساده LIKE و توابع Full-Text، دستور LIKE را در آموزش های مقدماتی به صورت جداگانه و مفصل توضیح داده ایم اما یکی از قابلیت های خوب MySQL که از نسخه 3.23 به بعد به آن اضافه شده، توابع Full-Text است که می تواند جهت کسب نتایج جستجوی سریع و تقریبا دقیق مورد استفاده قرار گیرد، هرچند برخی از قابلیت های Full-Text مربوط به کلمات انگلیسی است ولی توانایی آن برای کلمات فارسی آنقدر هست که بتوانیم بدون مشکل از آن استفاده کنیم و یا لااقل یکی از متدهای جستجو را بر مبنای آن قرار دهیم و در متدهای دیگر به فرض از LIKE استفاده نمائیم، در ادامه به توضیح اینکه چرا و چگونه از این قابلیت در کدهای PHP استفاده کنیم خواهیم پرداخت.

چرا باید از Full-Text به جای LIKE یا در کنار آن استفاده کنیم؟


واقعیت این است هر کدام از روش های بالا دارای معایب و محاسنی هستند، به عنوان مثال استفاده از دستور LIKE معمولا نتایج بیشتری را برمی گرداند، شیوه نگارش و استفاده از LIKE ساده تر و به اصطلاح دم دستی تر است اما در عوض ممکن است نتایجی نامربوط یا تکراری داشته باشیم، از طرفی جستجو با متد LIKE در پایگاه داده MySQL مخصوصا در مورد جداولی که محتوای زیادی دارند در مقایسه با Full-Text زمانبرتر است و پردازش کار در این حالت به طور معمول فشار بیشتری به سرور وارد می کند که این موضوع برای سرورهای با توان سخت افزاری پائین می تواند یک مشکل اساسی باشد، علاوه بر موارد گفته شده برخی قابلیت های Full-Text با دستور LIKE بدست نمی آیند که این به ماهیت متفاوت این دو روش برمی گردد.

ایجاد قابلیت Full-Text در جداول MySQL


قابلیت جستجوی Full-Text بر روی ستون هایی از نوع CHAR ,VARCHAR و TEXT و موتور MyISAM قابل اعمال است و هم زمان با ایجاد جدول یا بعد از آن نیز می توانیم به ستون مورد نظر آن را اضافه کنیم، به طور مثال در پرس و جوی نمونه زیر هم زمان با ساخت جدول، قابلیت جستجوی Full-Text را برای ستون فرضی title در نظر گرفته ایم:
CREATE TABLE post(
title VARCHAR(255),
FULLTEXT KEY title(title)) ENGINE=MyISAM
همان طور که اشاره شد می توانیم بعد از ساخت جدول و ستونها نیز جستجوی Full-Text را اضافه کنیم، برای افزودن این قابلیت بعد از ساختن جدول و ستونها، مقادیر SQL زیر را اجرا می کنیم:
ALTER TABLE post ADD FULLTEXT(title);
به این صورت این قابلیت به جدول و ستون موجود اضافه می شود.

شیوه جستجو در Full-Text


شیوه جستجو در Full-Text بر اساس MATCH() ... AGAINST صورت می گیرد:
SELECT title FROM post
WHERE MATCH (title) AGAINST ('$searchword');
برای جستجو از چند ستون در مقادیر MATCH می توانیم از کاما استفاده کنیم، همچنین می توان از قابلیت امتیاز دهی (score) این تابع نیز جهت چینش نتایج استفاده کرد:
SELECT *, MATCH (title) AGAINST ('$searchword') AS score FROM post
WHERE MATCH (title) AGAINST ('$searchword') ORDER BY score ASC
باید توجه کرد که Full-Text برای ایندکس کلمات محدودیت هایی اعمال می کند، از جمله اینکه اگر کلمه ای کمتر از 4 کاراکتر باشد ایندکس نمی شود، اگر کلمه ای در بیش از 50% ردیف ها تکرار شود ایندکس نمی شود، اگر کلمه ای در لیست Stopword ها باشد ایندکس نمی شود (البته این ویژگی مخصوص حروف انگلیسی است) و نهایتا اینکه برای شروع ایندکس کلمات برای جستجوی  Full-Text نیاز به وجود حداقلی از اطلاعات در ردیف ها است.

قابلیت های جستجو در Full-Text


قابلیت های دیگر این تابع جستجوی IN BOOLEAN MODE است که امکانات بیشتری در اختیارمان قرار می دهد (اضافه شده به MySQL از نسخه 4.0.1)، با استفاده از این قابلیت می توانید شمول ابتدا و انتهای یک کلمه را در جستجو تعیین کنید:
SELECT * FROM post WHERE MATCH (title) AGAINST ('+phpcode -htmlcode' IN BOOLEAN MODE);
در مثال بالا اگر کاربر عبارت code را جستجو کند، تیترهای حاوی عبارت phpcode در جستجو خواهند آمد اما تیتر های حاوی عبارت htmlcode در لیست نتایج ظاهر نمی شوند، از ویژگی های جستجو در حالت BOOLEAN MODE نادیده گرفتن قانون 50% است.
اما قابلیت Full-Text با امکان دیگری کامل می شود که Query Expansion نام دارد، همانطور که از معنی Expansion (توسعه) برمی آید نتایج جستجوی معمولی با Full-Text به دلیل اعمال محدودیت ها و سخت گیری در ایندکس کلمات و یا استفاده از Stopword ها، ممکن است بعضا دربرگیرنده همه نتایج نباشد، با افزودن Query Expansion حداقل به لحاظ تئوری می توانیم موارد معمولی تر را نیز در لیست جستجو نشان دهیم:
SELECT title FROM post
WHERE MATCH (title)
AGAINST ('$searchword' WITH QUERY EXPANSION);
دسته بندی: آموزش کاربردی » MySQL
related مطالب بیشتر:
آموزش ساخت پنل ورود و خروج سایت با PHP و MySQL
تعویض کد امنیتی Captcha با Ajax و MySQL
آموزش حذف گروهی اطلاعات از MySQL با استفاده از چک باکس
آموزش ساخت فرم عضویت در سایت با PHP و MySQL
ساخت فید آر اس اس (RSS Feed) با استفاده از PHP و MySQL
دیدگاه
more ۷۳ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
ali
۱۱:۴۷ ۱۳۹۴/۰۲/۱۸
سلام
من میخوام یک قسمت جست و جو برای مطالب سایتم داشته باشم اما نمیدونم چطوری..... اگه میشه لطفا کمکم کنین ...... مرسی
باید با چند مورد به اندازه کافی آشنایی داشته باشید:
- کار با تگ form در HTML.
- کار با متدهای GET و POST در PHP.
- کار با LIKE و مشتقات آن در MySQL و سپس در صورت نیاز آشنایی با قابلیت Full-Text یا طراحی سیستم جستجو بر اساس الگوریتم های شخصی.
احسان
۱۸:۵۸ ۱۳۹۴/۰۱/۲۶
با سلام و خسته نباشید من میخواستم بدونم
SELECT title FROM post
WHERE MATCH (title)
AGAINST ('$searchword' WITH QUERY EXPANSION);
در این کد بالا که از searchword استفاده کردید از دیتابیس خوانده میشود؟
و یک سوال دیگه کاربری کلمه ای رو جستجو کرد آیا لازم اون کلمه داخل دیتابیس ذخیره بشه یا نه؟
چون گیج شدم. اگه امکانش هست راهنماییم کنید اگر هم مثال بزنید بهتر میشود
برای استفاده از این آموزش لازم است که ابتدا با موارد مقدماتی MySQL آشنایی داشته باشید، searchword در واقع عبارتی است که کاربر از طریق فرم جستجو به سرور ارسال می کند، قاعدتا وقتی کلمه ای جستجو می شود، نیازی به ذخیره در دیتابیس نیست، بلکه صرفا وجود این عبارت با توجه به سایر تنظیمات در اطلاعات موجود بررسی و نتایج برگردانده می شوند، توصیه می کنیم ابتدا نحوه جستجو با LIKE را فرا بگیرید.
سعید
۲۱:۲۷ ۱۳۹۳/۱۱/۱۶
با سلام من کدی مثل کد زیر دارم مایلم تنها 10 نتیجه آخری که به sql اضافه کردم را نمایش دهد
$dbresult = mysqli_query($dblink, "SELECT * FROM `karbar` ORDER BY id DESC LIMIT 10");
سلام
باید کار با ORDER BY، چینش با ASC DESC و LIMIT در MySQL را فرا بگیرید، کد بالا به صورت نمونه و صرفا جهت راهنمایی بر اساس ستون فرضی id ویرایش شد (اگر ستون id در جدول شما وجود ندارد از ستونی استفاده کنید که در جدول وجود داشته باشد).
سعید
۲۰:۴۴ ۱۳۹۳/۱۱/۱۶
با سلام من تابعی شکل زیر دارم می خواهم نتیجه جست و جوی من همان کلمه باشد نه شکل آن
$sql = "SELECT * FROM `karbar` WHERE `sname` LIKE '%".$key ."%';";
می خواهم Like نباشد
ممنون می شوم کمکم کنید
پرس و جو را به صورت زیر تغییر دهید.
$sql = "SELECT * FROM `karbar` WHERE `sname` = '".$key ."';";
سارا
۲۱:۴۰ ۱۳۹۳/۰۶/۱۶
با سلام من به یه مشکل خوردم برای جستجو
زمانی که کلمه مورد نظر را برای سرچ تایپ میکنم و بعد دکمه سرچ رو میزنم وقتی میخواد سرچ کنه به جای سرچ کد فایل php مو نشون میده
تو رو خدا کمکم کنید........
قاعدتا مشکلی در کدهای شما وجود دارد که نیاز به بررسی است!
۱۲:۳۲ ۱۳۹۳/۰۵/۰۹
استاد من یه سوال دیگه هم دارم نظر شما در مورد پست میهمان چیست به تازگی در وبسایتم این قابلیت رو گذاشتم میخواستم نظرتون رو بدونم
با تشکر
لطفا از طرح سوالات کلی خودداری کنید! منظورتان از چه لحاظی است؟ از نظر اعتبار؟ از نظر کارایی؟ از نظر سئو یا...؟
پست مهمان یک قابلیت کاربردی است که در CMS ها معمولا با یک افزونه پیش فرض قابل ایجاد است و هدف آن انتشار مطالب توسط کاربران بدون عضویت در سایت است، سایت های مشابه را بررسی کنید، اگر چنین قابلیتی واقعا کاربرد داشته و مورد نیاز است، قاعدتا استفاده از آن برای شما نیز کاربردی خواهد بود.
۱۲:۲۵ ۱۳۹۳/۰۵/۰۹
استاد من یه کد دارم مانند کد ذیل میخوام بجای جستجو به حالت post در فرم به صورت مولفه get جستجو کند باید چه تغییری در کد ایجاد نمایم
با تشکر اوس
حذف شد
سوال کلی است، جواب کوتاه این است که متد فرم GET باشد و اطلاعات نیز در PHP با GET گرفته شوند، با این حال تغییر در یک کد تنها به یک مورد خلاصه نمی شود، باید بدانید دقیقا چه بخش هایی نیاز به تغییر دارند و چه بخش هایی خیر، لطفا به مبحث متد GET و POST در PHP مراجعه کنید.
mojtaba
۱۴:۲۴ ۱۳۹۳/۰۳/۲۵
سلام. سایتتون عالیه . من تا الان زیاد از مطالبش استفاده کردم.
میخوام بدونم چطور میشه توی یه فایل ورد با پی اچ پی جستجو کرد.
تا آنجا که اطلاع داریم انجام این کار نیازمند نصب کتابخانه های مجزا مانند Antiword در PHP است که به دردسر آن نمی ارزد!
mostafa
۱۱:۴۵ ۱۳۹۳/۰۱/۲۱
ممنون روش خوبی هست فکر کنم بشه از یه تریگر on insert روی جدول اصلی استفاده کرد تا اطلاعات رو به جدول های دیگه بسط بدیم فقط من نمی دونم کدش چیه میشه مثال بزنید اگه یه کاربر با id جدید وارد جدول اصلی شد همان id در یک جدول دیگه ثبت بشه. با تشکر
کدهای شما باید تا حد امکان مبتنی بر امکانات و توابع PHP باشند نه دیتابیس، چون در این صورت ممکن است در نسخه های مختلف MySQL به یک شکل عمل نکنند ضمن اینکه مدیریت برنامه و به طور مثال خطایابی در این حالت دشوار است، بهترین حالت ممکن نوشتن دستورات به صورت متدها و شرط ها در خود PHP است، به طور مثال اگر پرس و جوی اول صحیح اجرا شد، ID کاربر دریافت و در جدول دوم درج شود و... باید سعی کنید برای اینها دستورات پیوسته و هدفمند تعریف کنید.
mostafa
۱۶:۴۴ ۱۳۹۳/۰۱/۲۰
سلام ببخشید من چند تا جدول دارم که هر جدول یه فیلد id داره که صفت auto_increment واسش تعریف شده وقتی یه کاربر ثبت نام میکنه یک سطر در تمام جدول ها با نام کاربر اضافه میشه میخواستم بدونم ایا id کاربر در تمام جدول ها یکی میشه مثلا در تمام جدول ها 12 بشه یا اینکه ممکنه در یه جدول 12 بشه در یه جدول 14 چون موقع join کردن جدول ها شرط رو بر مبنای id قرار میدم ایا احتمالش هست اشتباه پیش بیاد؟
هر چند با احتمال ضعیف، اما امکان مختل شدن دیتابیس وجود دارد، فرض کنید به هر دلیل کدهای شما پرس و جوی مربوط به یک جدول را اجرا کنند و برای پرس و جو های دیگر با خطا مواجه شوید، در دور بعدی یک جدول مقادیر به فرض 12 خواهد بود، اما جداول دیگر یک مقدار عقب تر هستند، باید طوری برنامه بنویسید که در صورت بروز اتفاقات ناخواسته، سیستمتان به طور کلی مختل نشود، به طور مثال ابتدا اطلاعات یک جدول به روزرسانی شود، سپس متناسب با نام کاربر یا هر چیز یکتای دیگر، شماره ID او از جدول اصلی گرفته و به جداول دیگر منتقل شود یا هر روش دیگری که به ذهنتان می رسد.
saed
۱۳:۲۵ ۱۳۹۲/۱۲/۲۲
با سلام
من هر کاری که می کنم، نمی تونم با فول تکست یه کلمه ی 3 کاراکتری رو سرچ کنم، توی گوگل که سرچ می کنم، می گه باید از این یه خط کد استفاده کنی :
ft_min_word_len=3
ولی خب کجا باید از این استفاده کنم؟ تازه مگه شما نگفتید همچین مواقع باید از WITH QUERY EXPANSION استفاده بشه ؟
الان من چی کار کنم ؟؟؟؟؟
ممنون
ظاهرا QUERY EXPANSION تنها موارد خاصی را توسعه می دهد، در کل FULL TEXT ایرادات زیادی دارد و صرفا این آموزش جهت اطلاعات بیشتر می تواند استفاده شود!
ft_min_word_len در تنظیمات اصلی سرور قرار دارد و به راحتی قابل ویرایش نیست (آموزش خاص دارد و توصیه نمی شود!).
الهام
۱۹:۳۱ ۱۳۹۲/۱۲/۰۹
سلام ما یه جستجو داریم به طوری بر اساس تاریخ جستجو رو انجام میده حتی ترکیبش با radio ها کار می کنه مثلا من تاریخ رو بدم و نام کتاب رو که با انتخاب radio نام کتاب هستش رو بدم در بین اون تاریخ تمام کتاب های هم اسم جستجو شده رو نشون میده اما اگه تاریخ رو انتخاب نکنیم و فقط radio نام کتاب رو بزنیم و جستجو کنیم می گه چیزی یافت نشد این دو تا خط دستوره که کار نمی کنه و خطایی هم نداره
if($radio=='code_book' && $f=="" && $t=="")
$sql ="SELECT b.titlebook,b.code_book,a.* FROM amanat as a,book as b WHERE b.titlebook LIKE '%$search%' AND state=0 AND b.code_book=a.code_book";
if($radio=='code_cust' && $f=='' && $t=='' )
$sql = "SELECT * FROM amanat WHERE state=0 AND code_cust LIKE '$search' ";
و اینم کل دستور دکمه جستجو
if (isset($_GET['btn_search'])){
$search=$_GET['search'];
$radio=$_GET['radio'];
$f=$_GET['from'];
$t=$_GET['to'];

$sql ="SELECT * FROM amanat WHERE state=0 and timeset BETWEEN LIKE'$f' AND LIKE'$t'";
if($radio=='code_book' && $f=="" && $t=="")
$sql ="SELECT b.titlebook,b.code_book,a.* FROM amanat as a,book as b WHERE b.titlebook LIKE '%$search%' AND state=0 AND b.code_book=a.code_book";
if($radio=='code_book')
$sql ="SELECT b.titlebook,b.code_book,a.* FROM amanat as a,book as b WHERE b.titlebook LIKE '%$search%' AND state=0 AND b.code_book=a.code_book and timeset BETWEEN '$f' AND '$t'";
if($radio=='code_cust' && $f=='' && $t=='' )
$sql = "SELECT * FROM amanat WHERE state=0 AND code_cust LIKE '$search' ";

if($radio=='code_cust')
$sql ="SELECT * FROM amanat WHERE code_cust LIKE '$search' AND state=0 AND timeset BETWEEN '$f' AND '$t'";

$res= mysql_query($sql)or die(mysql_error());
$num_rows=mysql_num_rows($res);

if($num_rows){
while($row=mysql_fetch_array($res)){
?>
میشه بگین باید چی بگیم تاریخمونم با datapicker هستش و دو تا تکست داریم و بعدم دو تا radio که براساس نام کتاب کد ملی و یه دونه تکس برای جستجوهای این دو تا radio ها داریم حالا میخوایم بگیم وقتی دو تا تکس تاریخ خالی هم بود جستجو Radio ها انجام بشه
ممنون میشم کمکم کنید.
می توانید ست شدن تاریخ یا نشدن آن را با یک دستور شرطی بررسی کنید، اگر خالی بود (یا ست نشده بود) یک نوع پرس و جو (بدون قسمت BETWEEN) را اجرا کنید، اگر ست شده بود، پرس و جوی حالت فعلی را اجرا کنید، باید کدنویسی بلد باشید، به علت کمبود فرصت امکان نوشتن کدها نیست.
نکته: با توجه به قدیمی و منسوخ شدن اکستنشن mysql بهتر است به جای آن از mysqli یا PDO استفاده کنید.
الهام
۲۲:۳۷ ۱۳۹۲/۱۲/۰۷
سلام سوالام براتون ثبت نشده؟
پاسخ سوال شما نیاز به بررسی دقیق کدها دارد (کل فایل باید ارسال شود)، لطفا در صورت تمایل از طریق ایمیل (که در بخش تماس با ما) وجود دارد، فایلتان را ارسال کنید.
الهام
۲۱:۴۸ ۱۳۹۲/۱۲/۰۵
ممنون درست شد لطف کردید سوالات دیگری که در مورد جستجو دارم یکی اینکه من برای گزارش گیریم دستور زیر رو نوشتم اما جستجو بین دو تاریخ رو در نظر نمیگیره و تمام اونایی که state=1 هستش رو در نظر میگیره و خطایی هم نداره اما دو دستور radio ها کار می کنه و چون جستجوی بین دو تاریخم کار نمی کنه نمی تونم ترکیبشون کنم من میخوایم به طوری باشه که بین اون تاریخ کتابایی امانت دادم یا افرادی که کتاب امانت گرفتن رو نشون بده
if (isset($_GET['btn_search'])){
$search=$_GET['search'];
$radio=$_GET['radio'];
$f=$_GET['from'];
$t=$_GET['to'];
if($f=='from' && $t=='to'){
$sql = mysql_query("SELECT * FROM amanat WHERE timeget BETWEEN '$f' AND '$t' AND state=1 ",$con);
}elseif($radio=='code_book')
$sql = mysql_query("SELECT b.titlebook,b.code_book,a.* FROM amanat as a,book as b WHERE b.titlebook LIKE '%$search%' AND state=1 AND b.code_book=a.code_book ",$con);
elseif($radio=='code_cust')
$sql = mysql_query("SELECT * FROM amanat WHERE code_cust LIKE '$search' AND state=1",$con);
و سوال دیگم اینه که ما یک جستجو داریم که صفحه بندیش کردیم اما وقتی صفحه دوم رو میزنیم دیگه بقیه جستجو که باید در صفحه دوم قرار میگرفت رو نشون نمیده و خالی برای این مشکلمون چی کار باید بکنیم؟
در درجه اول باید ببینید تاریخ ها با چه فرمتی به کدهای PHP داده می شوند، با استفاده از دستور echo ساده می توانید موارد ارسالی را خروجی گرفته و تست کنید، نکته دوم اینکه ستون مورد نظر باید از نوع DATETIME باشد، در این صورت می توانید از نمونه پرس و جوی زیر استفاده کنید:
SELECT * FROM `table` WHERE CREATE_TIME > "2014-01-01" and CREATE_TIME < "2014-01-30"
همچنین نمونه زیر را هم تست کنید:
SELECT * FROM `table` WHERE CURDATE() BETWEEN "2014-01-01" AND "2014-01-30"
در مورد سوال دوم، بدون بررسی کدها نمی توان پاسخ دقیقی داد، ممکن است مشکل از ست کردن نادرست پارامترهای مورد نیاز در لینک صفحات باشد، به فرض عبارت جستجو شده ارسال نشود یا اینکه صفحه بندی مشکلی داشته باشد و یا اینکه به درستی در پرس و جو جایگزین نشده باشد.
الهام
۱۸:۳۲ ۱۳۹۲/۱۲/۰۵
چرا صفحه php هستش
و اینم کد من
 <input name="search" type="text" id="input1" size="20" maxlength="255" value="<?php echo $_GET['search']; ?>" />
و وقتی تو مرورگر اجرا می کنم در ابتدا
با این خطا داخل تکس روبرو میشم
<br /><b>Notice</b>:  Undefined index: search in <b>C:\xampp\htdocs\proje library\backbook.php</b> on line <b>27</b><br />
و این در صورتی که search تو خودش تعریف شدست
اما بعد از اینکه من داخل اون متن رو بنویسم و جستجو کنم مقدار درش باقی می مونه اینم دستور دکمه سرچم
    if (isset($_GET['btn_search'])){
$search=$_GET['search'];
$re=mysql_query("SELECT * FROM amanat WHERE code_cust LIKE '$search' and state=1")or die(mysql_error());
اینم از فرم که متدش get هستش
<form id="form1" name="form1" method="get" action="">
حالا میشه راهنمایی کنید که مشکل از چیه ؟
برای حل مشکل خطا، ابتدای متغیر
$_GET['search']
علامت @ قرار دهید!
کد مورد دیگری ندارد.
نکته: با توجه به قدیمی و منسوخ شدن اکستنشن mysql بهتر است از mysqli یا PDO استفاده کنید.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
3 × 1
20 × 20
=