چهارشنبه ۰۳ اردیبهشت ۱۴۰۴

Wednesday, April 23, 2025 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
هوشمند سازی پنل ورود و خروج سایت با PHP و MySQL
تعویض کد امنیتی Captcha با Ajax و MySQL
آموزش ساخت پنل ورود و خروج سایت با PHP و MySQL
ایجاد لینک دانلود مدت دار با PHP و MySQL
دیدگاه
more ۷۳ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
الهام
۲۱:۲۹ ۱۳۹۲/۱۲/۰۴
ببخشید اینو بلدم اما با این روش تا من برم تو اون صفحه کد نمایش داده میشه تو اون تکست و این از نظر ظاهری اصلا خوب نیست من دنبال روش دیگه ایم
صفحه شما PHP است؟ در این صورت نباید کدی خروجی داده شود، اگر کد را در تکست فیلد می بینید یک جای کار اشتباه است، تنها خروجی زمانی نمایش داده می شود که متنی در فیلد وارد و سپس فرم را ارسال کنید، متن از طریق متد GET به فایل PHP ارسال و در متغیر قرار داده می شود، سپس با دستور echo از متغیر در قسمت value فرم خروجی می گیریم، این روشی استاندارد است و راه حل جایگزین خاصی نه نیاز است و نه وجود دارد!
الهام
۱۹:۰۱ ۱۳۹۲/۱۲/۰۴
سلام
ببخشید من روشی رو میخواستم که متنی که جستجو می کنم بعد از اینکه دکمه جستجو رو میزنم بازم باقی بمونه که من بفهمم چی رو جستجو کردم
ممنون میشم در این مورد کمکم کنید
روش پیچیده ای ندارد، مقادیر کلمه جستجو شده را از طریق متد GET دریافت کنید و با ترکیب PHP و HTML در قسمت value تگ input با دستور echo مقادیر را چاپ نمائید، مثال:
<input name="search" id="search" type="text" maxlength="255" value="<?php echo $search ?>" />
haniyeh
۲۱:۱۵ ۱۳۹۲/۱۱/۱۳
سلام. بازم یه زحمتی دارم براتون. میشه کد سبد خرید رو هم برام بفرستین. خواهشا کمکم کنید باید پروژم رو کار کنم
خدمات سایت شامل ارائه اسکریپت آماده و... نمی شود، لطفا به سایت های دانلود اسکریپت مراجعه کنید.
haniyeh
۱۳:۱۸ ۱۳۹۲/۱۱/۱۳
با سلام.
من کد دستور جستجو رو می خوام البته زبان php رو می خوام. برای یه سایت کتابفروشی می خوام یه جستجو بزارم ولی موفق نمی شوم اگه میشه کدها رو برام بزارین ممنونتون میشم.
با تشکر از اموزش های خوبتون من همیشه استفاده می کنم
هیچ کدی که متناسب با سایت شما باشد از قبل وجود ندارد! باید کدها را متناسب با سیستم سایتتان بنویسید یا از نمونه های موجود در وب الگوبرداری کنید (کدی آماده در اختیار نداریم).
قلی پور
۱۳:۴۷ ۱۳۹۲/۱۱/۱۲
سلام. میشه بگید توی php چطور باید search رو قرار بدم تا کار کند ؟
برای قرار دادن امکان Search در PHP باید برنامه نویسی PHP و کار با مواردی مانند LIKE در MySQL را فرا بگیرید تا بتوانید کدهای این بخش را تعریف کنید.
ابوالفضل
۱۹:۳۳ ۱۳۹۲/۱۱/۰۱
سلام من یه مشکلی دارم با جستجوگر سایتم زمانی که عبارات دارای یک حروف عربی مثلا ي و ک عربی هستش جستجو نتیجه ای ندارد! آیا روشی هست تا بتوان در صورت موجود بودن این کلمات در عبارت آنها را به واژه فارسی تغییر داد و بعد جستجو صورت گیرد؟
ممنون
می توانید قبل از استفاده از عبارت در پرس و جو، مانند نمونه زیر آن را اصلاح کنید:
<?php
$str = 'تستي';
$str = str_replace('ي', 'ی', $str);
echo $str;
?>
نکته: بهتر است دیتابیس و کدهایتان را طوری طراحی کنید که کاراکترها به صورت فارسی (نه به صورت ناخوانا) ذخیره و بازیابی شوند، برای این منظور در درجه اول باید Server connection collation دیتابیس را
utf8_persian_ci
انتخاب کنید، سپس برای اینکه کاراکترها به صورت فارسی در دیتابیس ذخیره شوند مراحل زیر را انجام دهید:
- از متاتگ زیر در تمام صفحات استفاده کنید:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- علاوه بر دیتابیس، جداول و ستون ها را نیز با یونیکد
utf8_persian_ci
بسازید.
- پس از اتصال با دیتابیس، پرس و جوی زیر را هم اجرا کنید:
mysqli_query($conn, "SET NAMES 'utf8'");
ابوالفضل
۰۰:۲۵ ۱۳۹۲/۱۰/۲۸
سلام بی نهایت از پاسخدهیتون سپاسگذارم باور کنید سایت شما خیلی بهم کمک کرد ای کاش مطلبی در مورد نحوه ذخیره ایمن اطلاعات در بانک های اطلاعاتی و همچنین نحوه گرفتن حفره های امنیتی سایت هم قرار می دادید به هر حال لازم می دونم بازم ازتون تشکر کنم بابت سایت خیلی خوبتون و همچنین وقتی که برای پاسخگویی به نظرات ما می گذارید...
ابوالفضل
۱۴:۱۱ ۱۳۹۲/۱۰/۲۷
با سلام ممنون از پاسخدهیتون مشکل را با کمک راه حلی که شما فرمودید برطرف ساختم اما سوالی که حالا برای بنده پیش آمده این است که اگر این حفره امنیتی وجود داشته باشد چگونه می توانند به سایت نفوذ کنند یه توضیح مختصری در این مورد بیان نمایید
با تشکر از شما
این نوع حفره امنیتی به حملات MySQL injection معروف است، در این حالت هکر می تواند پرس و جوی کدهای شما را بر اساس خواسته خود تغییر دهد، به فرض اگر مقادیر ارسالی کاربر به صورت زیر باشد و ایمن سازی نشود:
$user = "' OR 1'";
در پرس و جو می توان آن را به صورت زیر وارد کرد:
SELECT * FROM tbl WHERE user = '' OR 1''
که در این حالت تمام نتایج فراخوانی می شوند، حالت های بدتر می تواند شامل اجرای دستورات حذف جداول و... باشد.
ابوالفضل
۲۱:۳۱ ۱۳۹۲/۱۰/۲۵
با سلام
در قسمت جستجوی سایت من زمانی که عبارت ,,;',,, این چنینی جستجو می شود خطای زیر داده می شود دلیل چیست ؟؟ و برای رفع آن باید چه کاری انجام داد ممنون میشم جواب بدین
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ',','','words','word')' at line 1
به احتمال زیاد کدنویسی سیستم مدیریتی سایت شما دچار حفره امنیتی است و اطلاعات پیش از استفاده در پرس و جوی MySQL به درستی ایمن سازی نمی شوند، اگر از اکستنشن mysqli استفاده می کنید، حتما از تابع mysqli_real_escape_string استفاده کنید.
فروغ
۰۰:۱۶ ۱۳۹۲/۱۰/۱۳
با سلام. می خواستم بدونم در این تکه کد که از پست یکی از دوستان برداشتم منظور از علامت % چیست؟
ممنون میشم اگه جواب بدید
where `name` like "%hello%" or `name` like "%test%"
علامت % در ابتدا و انتهای LIKE، دامنه شمول جستجو را مشخص می کند، به فرض اگر به دنبال عبارت "نویس" باشیم، حالت LIKE% عبارت "بنویس" را شامل می شود، حالت %LIKE عبارت "نویسی" و حالت %LIKE% عبارت "بنویسیم" و... را شامل می شود.
لطفا برای کسب اطلاعات بیشتر به آموزش های مقدماتی MySQL مراجعه کنید.
مرتضی
۲۱:۰۷ ۱۳۹۲/۱۰/۱۱
سلام خسته واقعا نباشید
من میخوام واسه پروژه ام یه قسمت search بزارم که اگه اسم یا کد مخصوص یه فیلد رو وارد کنم تمام مشخصات اون رو نمایش بده؟
اگه زحمتش رو بکشین زود جواب بدین ممنونتون میشم آخه وقت زیادی ندارم باید تحویلش بدم
سوالتان کلی است و به ناچار پاسخ نیز کلی:
- باید برنامه نویسی با PHP را تا حدودی بلد باشید.
- در ساده ترین حالت، از LIKE در پرس و جوهای MySQL استفاده کنید.
۲۰:۱۱ ۱۳۹۲/۰۹/۱۰
سلام
من که نفهمیدم مشکلش از کجاست ...
$r=mysqli_query($conn, "select url from post where match(url) against('$url' with query expansion)");
echo mysqli_num_rows($r); // output ==> 203178
$r1=mysqli_query($conn, "select url from post where url like '$url'");
echo mysqli_num_rows($r1); // output ==> 2
حتی وقتی fetch میکنم تا ببینم مقدارش چیه با هم فرق می کنند ...
کوئری که با like نوشته شده درست است.
هر چند دقیقا مشکلتان را توضیح نداده اید، اما به نظر Full-Text قابلیتی قابل اتکا نیست، بهترین روش جستجو در دیتابیس نوشتن سیستم ایندکس کلمات و جستجو به صورت سفارشی است (چیزی شبیه گوگل) که قاعدتا پروژه ای سنگین محسوب شده و نیاز و به تسلط بالا دارد.
احمدی
۱۶:۰۳ ۱۳۹۲/۰۸/۲۹
با سلام چگونه از تمامی جدول های یک پایگاه داده جستجو کرد یعنی اگر یک پایگاه داده 5 جدول داشته باشیم کلمه مورد جستجو را در تمام جدول ها جستجو کند از یک جدول می شود جستجو کرد اما از چند جدول نتوانستم
برای این کار باید از پارامترهایی مانند INNER JOIN در نوشتن پرس و جو استفاده نمائید، مثال:
SELECT t1.col_1, t2.col_1
FROM `tbl_1` t1
INNER JOIN `tbl_2` t2 ON (t1.id = t2.id)
WHERE t1.id != ''
LIMIT 0 , 30
sanobar
۱۱:۲۶ ۱۳۹۲/۰۸/۱۶
سلام
اگه بخواهیم چند تا جمله یا کلمه رو در دیتابیس سرچ کنیم و هر ردیف که یکی از اون جمله های رو داشت به نتایج برگشتی اضافه کنه چطور باید با MATCH AGAINST نوشت ؟
مثلا این کلمات رو داریم :
hello , test
با like اینطوری میشه :
where `name` like "%hello%" or `name` like "%test%"
یه روش ساده تر هم هست
where `name` IN('test','hello')
حالا با MATCH AGAINST چطوری میشه نوشت ؟
از نمونه زیر استفاده کنید:
SELECT * FROM `tbl` WHERE MATCH(`col_1`) AGAINST('word_1') OR MATCH(`col_2`) AGAINST('word_2');
سعید
۱۰:۳۹ ۱۳۹۲/۰۷/۲۲
سلام
خسته نباشید
اگر برای ساخت موتور جستجوی سایت از کد زیر استفاده کنیم ایرادی ندارد؟ چون من قبلاً با کلمه REGEXP برخورد نکرده بودم.
$check = mysqli_query($conn, "SELECT id FROM tbl WHERE tit REGEXP '$item2|$item1|$item3'") or die(mysqli_error($conn));
اخه میدونید توی دستورات mysql یه دستور like داریم اما نمی دونم این دستور یهو از کجا پیداش شد. جالب اینجاست که خیلی هم دستور جمع و جوریه!
چون این دستور نتیجه میده صد در صد هم وجود داره اما می خواستم بدونم جزو توابع mysql حساب میشه یا ساختار اصلیه!
با تشکر و سپاس از شما
عملگر REGEXP جزء موارد استاندارد MySQL است:
http://dev.mysql.com/doc/refman/5.1/en/regexp.html
که با آن امکان استفاده از عبارات با قاعده در پرس و جوهای دیتابیس مهیا می شود، باید توجه داشته باشید که در کل LIKE روش سریع تر و بهینه تری نسبت به REGEXP است (هر چند REGEXP در مواردی کاربردهای خاص خود را دارد)، به همین دلیل استفاده از REGEXP در زمانی که می توانید از LIKE استفاده کنید، توصیه نمی شود.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
4 × 3
20 × 20
=