הוסטס - פורום אחסון האתרים הגדול בישראל

הוסטס - פורום אחסון האתרים הגדול בישראל (https://hosts.co.il/forums/index.php)
-   פורום תיכנות (https://hosts.co.il/forums/forumdisplay.php?f=14)
-   -   חיפוש בבסיס נתונים: Like מורחב? (https://hosts.co.il/forums/showthread.php?t=94985)

dor77 20-01-12 17:44

חיפוש בבסיס נתונים: Like מורחב?
 
שלום.
נגיד ויש לי משפט:

I want to work.

נניח ואדם חיפוש I want אז הכל בסדר, במידה והוא מחפש I work הוא לא מקבל כלום, למה?

אני רוצה שהחיפוש יהיה מאוד רחב.
חשבתי לקחת את המשפט, לפרק אותו למילים עם explode ואז להריץ LIKE על כל אחד אבל איך עושים זאת? איך מריצים את ה LIKE על כל אחד?

תודה!

אדיר 20-01-12 18:09

תקרא על MATCH AGAINST.

dor77 20-01-12 20:01

בקושי יש על זה מידע..
עשיתי כך:
HTML קוד:

$query = "SELECT * FROM `blabla` WHERE MATCH(`bla`) AGAINST('" . $search . "')"; 
שגיאה..
בטוח שאין שיטה יותר נוחה?

תודה.

Erez | TrustMedia.co.il 21-01-12 19:11

הגדרת את השדה בתור full text field (או משהו בסגנון, לא זוכר בדיוק)?
ויש עוד כל מיני מנועי חיפוש אבל זה הכי פשוט לשימוש שמגיע עם mysql

Itay 22-01-12 19:49

http://phpguide.co.il/%D7%97%D7%99%D...7%9C%D7%90.htm
יש פה הסבר די טוב על זה

זה הרבה יותר יעיל ומדוייק מלהשתמש בלייק, אבל בכל מקרה - את מה שאמרת עושים ככה:
PHP קוד:

<?php
$args 
= array('title''body''author'); // השמות של השדות בדאטהבייס
$query explode(' 'urldecode($_GET['q']));
$where = array();
$where[] = "1"// למקרה שאין כלום בשאילתה, תמיד אפשר לעשות WHERE 1 בלי שיקרה כלום
foreach($args AS $arg)
{
    
$curRun = array();
    foreach(
$query AS $word)
    {
        
$curRun[] = $arg." LIKE '%".mysql_real_escape_string($word)."%'";
    }
    
$where[] = "(".implode(" OR "$curRun).")";
}
$results mysql_query("SELECT * FROM table WHERE ".implode(" OR "$where));
?>

וכמובן שאתה יכול להחליף את ה-OR למ-AND אם זה מה שאתה מעדיף - אבל שוב, זה הרבה פחות יעיל

dor77 25-01-12 16:38

ציטוט:

נכתב במקור על ידי Itay (פרסם 833153)
http://phpguide.co.il/%D7%97%D7%99%D...7%9C%D7%90.htm
יש פה הסבר די טוב על זה

זה הרבה יותר יעיל ומדוייק מלהשתמש בלייק, אבל בכל מקרה - את מה שאמרת עושים ככה:
PHP קוד:

<?php
$args 
= array('title''body''author'); // השמות של השדות בדאטהבייס
$query explode(' 'urldecode($_GET['q']));
$where = array();
$where[] = "1"// למקרה שאין כלום בשאילתה, תמיד אפשר לעשות WHERE 1 בלי שיקרה כלום
foreach($args AS $arg)
{
    
$curRun = array();
    foreach(
$query AS $word)
    {
        
$curRun[] = $arg." LIKE '%".mysql_real_escape_string($word)."%'";
    }
    
$where[] = "(".implode(" OR "$curRun).")";
}
$results mysql_query("SELECT * FROM table WHERE ".implode(" OR "$where));
?>

וכמובן שאתה יכול להחליף את ה-OR למ-AND אם זה מה שאתה מעדיף - אבל שוב, זה הרבה פחות יעיל


תודה אבל החיפוש ממש גרוע!
זה הקוד:

$args = array('title'); //
PHP קוד:

השמות של השדות בדאטהבייס
$query 
explode(' 'urldecode($_GET['q']));
$where = array();
$where[] = "1"// למקרה שאין כלום בשאילתה, תמיד אפשר לעשות WHERE 1 בלי שיקרה כלום
foreach($args AS $arg)
{
    
$curRun = array();
    foreach(
$query AS $word)
    {
        
$curRun[] = $arg." LIKE '%".mysql_real_escape_string($word)."%'";
    }
    
$where[] = "(".implode(" OR "$curRun).")";
}
$results mysql_query("SELECT title FROM tutorials WHERE ".implode(" OR "$where));


while(
$rs mysql_fetch_array($results)) {
    
$cname $rs['title'];
    echo 
"$cname\n";


אם יש לי דבר כזה:

How to plan amazing trip

ואני מחפש: how to amazing
זה לא מוצא..למה?
תודה.

Itay 25-01-12 22:44

תריץ את השאילתא הזאת בדאטהבייס שלך (דרך ה-phpMyAdmin) ותגיד אם זה מחזיר משהו:
קוד:

SELECT title FROM tutorials WHERE 1 OR (title LIKE '%how%' OR title LIKE '%to%' OR title LIKE '%amazing%')

dor77 26-01-12 17:45

כן מחזיר..

Itay 26-01-12 19:47

אז תשנה את זה:
PHP קוד:

$results mysql_query("SELECT title FROM tutorials WHERE ".implode(" OR "$where)); 

לזה:
PHP קוד:

$results "SELECT title FROM tutorials WHERE ".implode(" OR "$where); 

ותדפיס את $results ותרשום פה את הפלט

dor77 26-01-12 19:55

החיפוש יותר נחמד אבל עדיין גרוע בכללי..
למשל יש לי:
How to plan amazing trip

אם אני רושם trip זה מוצא, אם אני רושם plan זה מוצא..אם אני רושם how to plan אז הוא מוצא אותו ממש ממש ממש למטה..כאילו הוא לא הכי רלוונטי כרגע..יש מעליו עשרות שיש בהם רק את המילה how למשל..

לא מבין את זה!
בבקשה עזרה, תודה! :)

Itay 27-01-12 13:58

אין פה שום חישוב של רלוונטיות לביטוי חיפוש במה שנתתי לך, אמרתי שעדיף לא להשתמש בזה..
MATCH AGAINST עושה את החיפוש הזה הרבה יותר טוב, הרבה יותר מהר והרבה יותר פשוט

dor77 27-01-12 14:45

גם זה לא פתר את הבעיה..חיפוש צולע במיוחד..
משתגע..
נוותר..
תודה.

Haimz 27-01-12 16:53

אולי תנסה לקרוא על זה: http://phpguide.co.il/%D7%97%D7%99%D...7%9C%D7%90.htm

dor77 27-01-12 17:18

ציטוט:

נכתב במקור על ידי HHaim (פרסם 833554)
אולי תנסה לקרוא על זה: http://phpguide.co.il/%D7%97%D7%99%D...7%9C%D7%90.htm

ניסיתי..לא משהו בכלל..
אני מחפש משהו שאם יש לי את המשפט הבא:

ילד חגג יום הולדת

אז אם ירשמו "ילד" יקבלו, אם ירשמו "הולדת" יקבלו..אם ירשמו "ילד הולדת" גם יקבלו..

תודה.

Haimz 27-01-12 20:47

משהו שרשמתי: (אין פה סידור של רלוונטיות)
PHP קוד:

<?php

    $connect 
mysql_connect("localhost","username","pass");
    
$db_select mysql_select_db("db"$connect);
    
    
$query "how to amazing hello man are you"// מילות חיפוש
    
$col "title"// העמודה
    
$density 2// אחד או שתיים - צפיפות המילים
    
    //---------------------------------------
    
    
$where = array();
    
$exploded explode(" "$query); // preg_split("/\s{1}/", $query);
    
$explode = array();
    
    if( 
$density == )
    {
        for( 
$x 0$x count($exploded); ++$x )
        {
            if( 
$x )
            {
                continue;
            }
            
            
$explode[$x] = trim($exploded[$x] . " " $exploded[$x 1]);
        }
    }
    else
    {
        
$explode explode(" "$query);
    }
    
    foreach( 
$explode as $q )
    {
        if( empty(
$q) )
            continue;
        
$where[] = $col" LIKE '%" .$q"%'";
    }
    
    
$whereSyntax implode(" OR "$where);
    
    if( !empty(
$whereSyntax) )
    {
        
$whereSyntax " WHERE " .$whereSyntax;
    }
    
    if( 
strtoupper(trim($whereSyntax)) == "WHERE" )
    {
        
$whereSyntax null;
    }
    
    
//---------------------------------------
    
    
$result mysql_query("SELECT " .$col" FROM tutorials" $whereSyntax);
    
    while( 
$row mysql_fetch_array($resultMYSQL_ASSOC) )
    {
        echo 
$row[$col] . "<br />\n";
    }

?>

אין פה סידור של רלוונטיות, יש לך אפשרות לשחק עם הצפיפות (המשתנה $density ) יכול להיות על אחד או שתיים, אם זה שתיים זה מחלק את המשפט מכל שתי מילים, אם זה על אחד זה מחלק אותו על כל מילה.

אבל כמו שאמרו לך פה, MATCH AGAINST זה הכי נוח לדעתי.

Itay 28-01-12 03:36

ציטוט:

נכתב במקור על ידי HHaim (פרסם 833575)
משהו שרשמתי: (אין פה סידור של רלוונטיות)
אין פה סידור של רלוונטיות, יש לך אפשרות לשחק עם הצפיפות (המשתנה $density ) יכול להיות על אחד או שתיים, אם זה שתיים זה מחלק את המשפט מכל שתי מילים, אם זה על אחד זה מחלק אותו על כל מילה.

אבל כמו שאמרו לך פה, MATCH AGAINST זה הכי נוח לדעתי.

אתה יודע שבלולאת for אתה קובע בכמה המשתנה עולה/יורד? אתה יכול במקום $x++ לרשום $x+=2 ולחסוך את התנאי שלך..
ד"א - אם הביטוי הוא אי זוגי זה יקצץ מילה בסוף

ועוד ד"א.. מה ההגיון פה?
PHP קוד:

 $whereSyntax implode(" OR "$where);
    
    if( !empty(
$whereSyntax) )
    {
        
$whereSyntax " WHERE " .$whereSyntax;
    }
    
    if( 
strtoupper(trim($whereSyntax)) == "WHERE" )
    {
        
$whereSyntax null;
    } 


Haimz 28-01-12 10:08

כנראה שלא פתחתי את הראש עד הסוף, לא נורא זה משהו מהיר שפשוט רשמתי, ברור שהוא לא הולך להעלות אותו ככה וצריך להעביר שינויים
בקשר להגיון, זה משהו שרשמתי לפני שהוספתי את התנאי הראשון, אז שכחתי להסיר את התנאי השני -_-

dor77 28-01-12 13:09

חיים תודה על הקוד..סביר..הוא מוצא טוב רק בהנחה שאני כותב את המילה הניישה, אחרך הרביעית הוא מוצא..למשל אם יש לי:

ילד הלך לגן ביום ראשון

אם מחפשים ילד הלך זה מוצא
אם מחפשים הלך לגן זה מוצא
אבל אם מחפשים ילד ראשון זה לא מוצא..

אני חייב שהחיפוש יהיה מעולה..אחרת אני אאבד המון גולשים כי רוב הטראפיק בא מהמנוע חיפוש שבאתר.

אשמח לעזרה, תודה!

Itay 28-01-12 13:30

אם היית מסתכל על הקוד שלו היית מבין שאין מצב שזה היה מוצא משהו ב-"ילד ראשון" כי זה מחפש את 2 המילים האלו ביחד (כשהצפיפות שם היא על 2)

אבל שוב נגיד לך - MATCH AGAINST
אם אתה רוצה חיפוש שעובד כמו שצריך, לפי רלוונטיות וכו' - זה הפתרון

הנה כמה דוגמאות
http://stackoverflow.com/questions/3...r-by-relevancy
http://stackoverflow.com/questions/7...-stackoverflow
http://stackoverflow.com/questions/7...r-by-relevance
http://www.phpbuilder.com/board/show...59&postcount=4

dor77 28-01-12 14:43

ניסיתי את כולם שם,
הבעיה היא שיש לי כותרת כזו:

How to plan a trip

אם רושמים trip זה מוצא, אם רושמים plan זה מוצא, אבל אם רושמים how to זה לא מוצא.
אני יודע שיש הגבלה על חיפוש מהסוג הזה אבל בכל זאת, החיפוש הזה במצבו הנוחכי לא טוב לי.
אסור לי שהחיפוש יהיה צולע אחרת כל ההשקעה על האתר לחינם.

עריכה:

קצת מוזר אבל נראה לי שככה זה הכי טוב..השאלה האם תקני לרשום כך..:

PHP קוד:


    $query = strtolower($_GET["q"]); // <?php

include ('config.php');
    
    
$query strtolower($_GET["q"]);
    
$pieces explode(" "$query);
    
$one $pieces[0];
    @
$two $pieces[1];
    
    
$result mysql_query("
    SELECT DISTINCT `title` FROM `tutorials` WHERE title LIKE '%$one%$two%' OR title LIKE '%$two%$one%'
    "
);
    
    while(
$row mysql_fetch_array($result))
    {
        echo 
$row['title'] . "<br />\n";
    }

?>

אפשרי?

כרגע זה די טוב..אני חושב.
תודה.

Itay 28-01-12 18:43

אם תעשה שני LIKE על ה-title זה יהיה יותר הגיוני, במצב שלך - מה אתה עושה אם יש לך ביטוי של 10 מילים?

בכל מקרה, זה לא מוצא לך בגלל שיש הגבלה על אורך של מילה מסויימת בדיוק בגלל מילים כמו to, a, i.. אמורה להיות דרך לשנות את זה, תריץ חיפוש בגוגל

dor77 28-01-12 19:45

כן, צריך לשנות את "ft_min_word_len=4" אבל אני לא מוצא איפה..
חיפשתי בגוגל, זה אמור להיות בקובץ my.cnf..לא מוצא אותו.
השאלה האם אני יוכל לערוך את זה בשרת שאקנה..

בכל אופן לשאלתי, איך שרשמתי מקודם, עם השני like וה- OR באמצע, זה בסדר?

ככה:

PHP קוד:


    $result 
mysql_query("
    SELECT DISTINCT `title` FROM `tutorials` WHERE title LIKE '%$one%$two%' OR title LIKE '%$two%$one%'
    "
); 

ניתן לכתוב ככה?
תודה.

Itay 28-01-12 21:04

עניתי לך על זה.. אתה יכול לכתוב ככה, אבל איך תעשה את זה בביטוי עם 10 מילים?
הקוד שהבאתי לך בהתחלה זה הפתרון למקרה הזה.. אבל בכל מקרה זה לא יעזור לך בחיפוש לפי רלוונטיות

dor77 29-01-12 09:11

האמת זה עובד ממש טוב, גם בכותרת עם 10 מילים.
אם תקין לרשום כך אז אשאיר כך.
תודה רבה!

Haimz 30-01-12 15:40

אם במקום רווח אתה שם אחוז (%) לא שידעתי על זה, במקום להפריד מילה מילה, לא יותר פשוט להחליף רווח באחוז? לדוגמה משהו כזה:
PHP קוד:

<?php
    $q 
urldecode($_GET['q']);
    
$q str_replace(" ""%"$q);
    
$result mysql_query("SELECT DISTINCT `title` FROM `tutorials` WHERE title LIKE '%" .$q"%'"); 
?>


dor77 30-01-12 16:13

צודק חיים, לא חשבתי על זה..אותו אפקט ויותר פשוט.

תודה!

AlmogBaku 01-02-12 06:13

ציטוט:

נכתב במקור על ידי HHaim (פרסם 833743)
אם במקום רווח אתה שם אחוז (%) לא שידעתי על זה, במקום להפריד מילה מילה, לא יותר פשוט להחליף רווח באחוז? לדוגמה משהו כזה:
PHP קוד:

<?php
    $q 
urldecode($_GET['q']);
    
$q str_replace(" ""%"$q);
    
$result mysql_query("SELECT DISTINCT `title` FROM `tutorials` WHERE title LIKE '%" .$q"%'"); 
?>


זה לא אותו הדבר כי אז הסדר חייב להיות זהה למשל
"aa bb cc"
יהפוך ל
"aa%bb%cc"

יימצא את:
"aa zz bb xx cc"
אבל לא ימצא את:
"bb xx aa zz cc"

Haimz 01-02-12 18:47

ציטוט:

נכתב במקור על ידי AlmogBaku (פרסם 833904)
זה לא אותו הדבר כי אז הסדר חייב להיות זהה למשל
"aa bb cc"
יהפוך ל
"aa%bb%cc"

יימצא את:
"aa zz bb xx cc"
אבל לא ימצא את:
"bb xx aa zz cc"

אני לא הצעתי את הפתרון הזה, כמו שציינתי, לא שמעתי עליו, פשוט הצעתי לו להחליף רווח באחוז אם הוא משתמש בזה.

kobisl 07-02-12 15:32

כמו שנאמר לפניי חיפוש עושים בעזרת הפונקציה MATCH (השדה title צריך להיות fulltext)
אפשר לבחור בנוסף עם הפונקציה LIKE ולסדר לפי רלוונטיות של MATCH
דוגמה:
PHP קוד:

SELECT * ,MATCH (titleAGAINST ('text search') as mach
 FROM table
 WHERE 
(MATCH (titleAGAINST ('text search') OR LIKE '%text search%'
 
ORDER BY mach DESC 

MATCH מחזיר לנו מספר FLOAT בין 0 ל 1 לפי רלוונטיות התוצאה לתשובה.
שים לב ש MATCH מוגדר בברירת מחדל להתעלם ממלים בנות פחות מ 4 אותיות, צריך לשנות בקונפיג ל 3 או 2 בכדי לקבל תוצאות יותר טובות.

dor77 07-02-12 15:44

ואיך משנים את ההגבלה הזאת?
באיזה קובץ?
איפה הוא נמצא?

תודה רבה!

kobisl 07-02-12 16:06

ציטוט:

נכתב במקור על ידי dor77 (פרסם 834521)
ואיך משנים את ההגבלה הזאת?
באיזה קובץ?
איפה הוא נמצא?

תודה רבה!

בקונפיג של ה MYSQL
בדרך כלל ב etc/my.cnf
תחפש בקובץ את המשתנה ft_min_word_len
ותשנה לו את הערך ל 2 בכל המקומות בקובץ אל תשכח לעשות ריסטרט לאפאצ'י =]

dor77 09-02-12 08:40

תודה רבה אבל איפה זה בשרת? למשל הוסטגאטור?
אפשר לשנות את זה בכל שרת?

kobisl 09-02-12 16:22

אם אין לך גישה לקבצי הקונפיג תבקש ממנהל השרת לעשות את זה אין סיבה שהוא לא יסכים...

dor77 09-02-12 17:44

תודה אבל אני לא מוצא את זה ב wamp..איפה זה?

תודה לכם.

kobisl 09-02-12 19:32

C:\wamp\bin\mysql\mysql5.5.16\my.ini
אם אין לך את המשתנה ft_min_word_len
פשוט תוסיף אותו בסוף:
[mysqld]
ft_min_word_len=2
אל תשכח לעשות ריסטרט ל WAMP


כל הזמנים הם GMT +2. הזמן כעת הוא 04:50.

מופעל באמצעות VBulletin גרסה 3.8.6
כל הזכויות שמורות ©
כל הזכויות שמורות לסולל יבוא ורשתות (1997) בע"מ