Ankündigung

Einklappen
Keine Ankündigung bisher.

"Intelligente" Suchfunktion PHP / MySQL

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • "Intelligente" Suchfunktion PHP / MySQL

    Guten Tag,

    ich sitze derzeit an einer Suchfunktion und bin auf ein Problem gestoßen.

    Ausgangssituation:
    Ich habe ein Input-Element für die Suche in einem "Forum". Gibt man dort etwas ein, erscheint darunter ein Auswahlmenü (selbst erstellt: Ajax) .. das funktioniert auch bisher.


    Jedoch habe ich folgendes Problem:
    Es wird in der MySQL Datenbank nach der Eingabe im Input-Element gesucht. Dabei wird jedoch die voreingestellte Reihenfolge der Ausgabe gewählt..

    Code:
    $get_result = mysqli_query($db,"SELECT item_1, item_2, item_3 FROM product WHERE item_1 like '%$search_str%' OR item_2 like '%$search_str%' OR item_3 like '%$search_str%'")or die("Error: ".mysqli_error($db));
        $get_result_rows = mysqli_num_rows($get_result);    
        if ($get_result_rows > 0)
        {
            while ($result_more = mysqli_fetch_array($get_result))
            {
            ?> <div class="search_item"><?php echo $result_more["item_1"]." ".$result_more["item_2"]." ".$result_more["item_3"]; ?></div>
            <?php
            }
        }
    Mein Ziel ist es, wenn folgende Sachen in der Datenbank vorhanden ist, diese zu splitten und zu nutzen (jeh nachdem in welcher Reihenfolge der Nutzer die Eingabe hat):
    Beschreibung Marke Stichwort
    Lautsprecher 5.1 Logitech Homecinema
    Lautsprecher X500 Philips Musik
    Lautsprecher X602 Teufel Musik
    Beispiele:
    Ich gebe "Lautsprecher" ein:
    1. Lautsprecher X602
    2. Lautsprecher Teufel
    3. Lautsprecher Philips
    4. Lautsprecher Logitech
    5. Lautsprecher Homecinema
    5. Lautsprecher Musik

    Ich gebe "Homecinema" ein:
    1. Homecinema Lautsprecher
    2. Homecinema Lautsprecher Logitech
    3. Homecinema Lautsprecher Logitech 5.1


    Ich gebe "Lautsprecher X602 T" ein:
    1. Lautsprecher X602 Teufel
    2. Lautsprecher X602 Teufel Musik


    Würde mich freuen wenn jemand Vorschläge oder Ideen hat.

  • #2
    Puh.
    Wenn man 3 Stunden lang brainstormed, stößt man vielleicht irgendwann auf eine Lösung die deiner Vorstellung nahe kommt... ich würde mir die Arbeit aber nicht machen wollen.

    Ich gebe "Lautsprecher X602 T" ein:
    1. Lautsprecher X602 Teufel
    2. Lautsprecher X602 Teufel Musik
    Laut aktueller Suche, würdest du mit dem Suchbegriff nichts finden, da stoßen wir schon auf das erste Problem.
    Eine mögliche Lösung wäre, die Suche auf einer extra Spalte durchzuführen, die die Daten als einzelnen String enthält.

    Ich gebe "Lautsprecher" ein:
    1. Lautsprecher X602
    2. Lautsprecher Teufel
    3. Lautsprecher Philips
    4. Lautsprecher Logitech
    5. Lautsprecher Homecinema
    5. Lautsprecher Musik
    Wenn du mehr Ergebnisse haben möchtest als du eigentlich Daten hast, kannst du zusätzlich zur extra Spalte auch noch zusätzliche Zeilen anlegen in denen du die Permutationen der Reihenfolgen anlegst.

    Abeeeeer... Warum ist Lautsprecher 5.1 nicht im Ergebnis? Das gleiche für X500. Wodurch wird festgelegt wann welcher Eintrag verändert werden soll?


    So wie du es dargestellt hast ist die Suche nicht intelligent, sondern willkürlich^^'
    [COLOR=#A9A9A9]Relax, you're doing fine.[/COLOR]
    [URL="http://php.net/"]RTFM[/URL] | [URL="http://php-de.github.io/"]php.de Wissenssammlung[/URL] | [URL="http://use-the-index-luke.com/de"]Datenbankindizes[/URL] | [URL="https://www.php.de/forum/webentwicklung/datenbanken/111631-bild-aus-datenbank-auslesen?p=1209079#post1209079"]Dateien in der DB?[/URL]

    Kommentar


    • #3
      Danke für die Antwort!

      Ich habe in meinem Beispielen nicht alle Möglichkeiten aufgezählt.

      Das ganze sollte eher so aussehn das dem Nutzer anhand seiner Eingabe weitere Vorschläge angezeigt werden, wie wohl seine Eingabe enden könnte. (So wie es zb. Amazon / Google macht)
      Sind also in der Datenbank 100 Lautsprecher eingetragen von verschiedenen Marken & Bezeichnungen, sollen bei der Eingabe von "Lautsprecher" weitere möglichkeiten angezeigt werden wie zb. "Lautsprecher [Marke]" und "Lautsprecher [Bezeichnung]".

      Im weiteren Verlauf würde ich schauen, das ganze mit einem Rankingsystem zu verknüpfen, wodurch dann eben festgelegt wird, wann welcher Eintrag angezeigt wird (Reihenfolge). <- Das steht hier aber nicht zur Debatte


      Beispiel:

      Datenbank:
      Lautsprecher | X512 | Phillips
      Lautsprecher | GS-232 | Logitech
      Lautsprecher | X882 | Teufel
      Lautsprecher | ML-882 | Teufel
      Lautsprecher | SL512 | Bose
      Lautsprecher | W900 | JBL

      Eingabe "Lautsprecher":
      - Lautsprecher X512
      - Lautsprecher GS-232
      - Lautsprecher X882
      - Lautsprecher ML-882
      - Lautsprecher SL512
      - Lautsprecher W900

      Eingabe "Lautsprecher T":
      - Lautsprecher Teufel
      - Lautsprecher Teufel X882
      - Lautsprecher Teufel ML-882

      Eingabe "Lautsprecher X":
      - Lautsprecher X512 Phillips
      - Lautsprecher X882 Teufel

      Eigentlich ist es folgende Sache: Es gibt 3 Spalten zur auswahl, jeh nach Nutzereingabe werden diese 3 unterschiedlich aneinandergereiht.
      WIE aneinandergereiht wird (logisches vorgehen) würde ich im nachhinein einbauen... jedoch schaffe ich es einfach nicht dieses aneinanderreihen in Kombination mit der Datenbank zu scripten.

      Kommentar


      • #4
        Eine separate Tabelle "tags" mit Fremdschlüssel auf die Artikel scheint mir da am sinnvollsten, über die dann gesucht wird.
        Alternativ kann man sicher auch eine ganz "wilde" Abfrage mit UNION und GROUP_CONCAT basteln.
        sorry, shift-taste kaputt

        Kommentar


        • #5
          Wenn die Suche komplexer wird, macht es häufig Sinn irgendwann für die Suche auf eine Datenbank umzusteigen welche genau für so etwas optimiert ist. Bsp. ElasticSearch.

          https://www.elastic.co/guide/en/elas...uggesters.html
          https://www.elastic.co/guide/en/elas...ompletion.html

          Kommentar


          • #6
            Ich hab hier ein Beispiel, das ist natürlich nur zum Ausprobieren für die lokale Entwicklungsumgebung.

            Du hast drei DB-Tables, hifi_manufacturers (da Stecken die Hersteller drin), dann eine hifi_categories (da stecken die Kategorien drin, wie Lautprecher, Car-Hifi, Plattenspieler, Verstärker), und eine hifi_models, da stecken die Modellbezeichnungen drin, mit zwei Zusatzfeldern zum join auf die IDs der Tables mit den Herstellern und den Kategorien. Sorry, wenn der Post etwas länger ausfällt.

            sql hifi_manufacturers:
            Code:
            CREATE TABLE `hifi_manufacturers` (
              `id` int(11) NOT NULL,
              `manufacturer_name` varchar(100) CHARACTER SET utf8 NOT NULL
            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
            
            INSERT INTO `hifi_manufacturers` (`id`, `manufacturer_name`) VALUES
            (1, 'Technics'),
            (2, 'Pioneer'),
            (3, 'JVC'),
            (4, 'Teufel'),
            (5, 'JBL');
            
            
            ALTER TABLE `hifi_manufacturers`
              ADD PRIMARY KEY (`id`);
            
            
            ALTER TABLE `hifi_manufacturers`
              MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
            COMMIT;
            sql hifi_categories:

            Code:
            CREATE TABLE `hifi_categories` (
              `id` int(11) NOT NULL,
              `category_name` varchar(100) NOT NULL
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
            
            INSERT INTO `hifi_categories` (`id`, `category_name`) VALUES
            (1, 'Lautsprecher'),
            (2, 'Kopfhörer'),
            (3, 'Car Hifi'),
            (4, 'Verstärker'),
            (5, 'Plattenspieler');
            
            ALTER TABLE `hifi_categories`
              ADD PRIMARY KEY (`id`);
            
            ALTER TABLE `hifi_categories`
              MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
            COMMIT;
            sql hifi_models

            Code:
            CREATE TABLE `hifi_models` (
              `id` int(11) NOT NULL,
              `model_name` varchar(100) CHARACTER SET utf8 NOT NULL,
              `fk_categories_id` int(11) NOT NULL,
              `fk_manufacturers_id` int(11) NOT NULL
            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
            
            INSERT INTO `hifi_models` (`id`, `model_name`, `fk_categories_id`, `fk_manufacturers_id`) VALUES
            (1, 'Ultima 40', 1, 4),
            (2, 'KS-AX3202', 3, 3),
            (3, 'Control 1G', 1, 5);
            
            
            ALTER TABLE `hifi_models`
              ADD PRIMARY KEY (`id`);
            
            
            ALTER TABLE `hifi_models`
              MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
            COMMIT;
            Nun kommt die Datei suchformular.html mit dem Formular und JS:
            HTML-Code:
            <!DOCTYPE html>
            <html lang="de">
                <head>
                    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                    <title>Live-Suche PHP Ajax MYSQL</title>
                    <style type="text/css">
                        body{
                            font-family: Arail, sans-serif;
                        }
                        /* Formatting search box */
                        .search-box{
                            width: 300px;
                            position: relative;
                            display: inline-block;
                            font-size: 14px;
                        }
                        .search-box input[type="text"]{
                            height: 32px;
                            padding: 5px 10px;
                            border: 1px solid #CCCCCC;
                            font-size: 14px;
                        }
                        .result{
                            position: absolute;        
                            z-index: 999;
                            top: 100%;
                            left: 0;
                        }
                        .search-box input[type="text"], .result{
                            width: 100%;
                            box-sizing: border-box;
                        }
                        /* Formatting result items */
                        .result p{
                            margin: 0;
                            padding: 7px 10px;
                            border: 1px solid #CCCCCC;
                            border-top: none;
                            cursor: pointer;
                        }
                        .result p:hover{
                            background: #f2f2f2;
                        }
                    </style>
                    <script src="http://code.jquery.com/jquery-3.3.1.min.js"
                        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
                    crossorigin="anonymous"></script>
            
                    <script type="text/javascript">
                        $(document).ready(function () {
                            $('.search-box input[type="text"]').on("keyup input", function () {
                                /* Get input value on change */
                                var inputVal = $(this).val();
                                var resultDropdown = $(this).siblings(".result");
                                if (inputVal.length) {
                                    $.get("dbsuche.php", {term: inputVal}).done(function (data) {
                                        resultDropdown.html(data);
                                    });
                                } else {
                                    resultDropdown.empty();
                                }
                            });
            
                            $(document).on("click", ".result p", function () {
                                $(this).parents(".search-box").find('input[type="text"]').val($(this).text());
                                $(this).parent(".result").empty();
                            });
                        });
                    </script>
                </head>
                <body>
                    <div class="search-box">
                        <input type="text" autocomplete="off" placeholder="HiFi Artikel wählen..." />
                        <div class="result"></div>
                    </div>
                </body>
            </html>
            Und schlussendlich noch dbsuche.php mit der Abfrage
            PHP-Code:
            <?php

            $dbh 
            = new PDO('mysql:host=localhost;dbname=test''root''');

            if(isset(
            $_REQUEST['term'])) {
               
            //$term = $_REQUEST['term'];
              
            $term filter_var($_REQUEST['term'], FILTER_SANITIZE_STRING);

               
            $stmt $dbh->prepare(

                       
            "SELECT * FROM hifi_models,
                        hifi_categories,
                        hifi_manufacturers
                            WHERE
                                fk_categories_id = hifi_categories.id
                            AND
                                fk_manufacturers_id = hifi_manufacturers.id
                            AND
                                (hifi_models.model_name LIKE :term
                                    OR
                                        hifi_categories.category_name LIKE :term
                                     OR
                                        hifi_manufacturers.manufacturer_name LIKE :term)"
                       
            );
                
            $stmt->execute(array(':term' => '%'.$term.'%'));

                if(
            $stmt->rowCount() > 0){
                    while(
            $row $stmt->fetch()) {
                        echo 
            "<p>" $row['category_name'] . " " .
                                     
            $row['manufacturer_name'] . " " .
                                     
            $row['model_name'] . "</p>";
                    }
                } else{
                    echo 
            "<p>Keine Ergebnisse gefunden...</p>";
                }
                } else {
                    
            print_r($dbh->errorInfo());
                }

            // close connection
            $dbh NULL;

            Nicht vergessen, die DB Settings in der PHP-Datei anzugleichen.

            Das ist nur für Dich zum Ausprobieren und Spielen gedacht, da sind böse Sachen drin wie "SELECT * ", keine klare Trennung von DB-Gedöns und Ausgabe, und so weiter, also bitte NICHT copy + paste und auf den Live-Server damit.

            EDIT: Es wäre natürlich noch wichtig, erst eine gewisse anzahl von Buchstaben eingeben zu müssen, damit die Suche greift. Und auch ein limit bei der Abfrage, sonst hat man ein Problem bei einem riesen Artikelstamm.

            Lieben Gruß und gute Nacht

            Miss Santrop

            Kommentar


            • #7
              Hallo, ich hatte leider keine Zeit zu schreiben!

              Ich bedanke mich bei allen für ihre Vorschläge, Ideen & Beispiele! (vor allem Miss Santrop)

              Ich werde mich mal daran versuchen und ausprobieren was in meinem Fall am besten geeignet wäre.
              Sollte ich zu einer Lösung kommen stelle ich sie hier rein!

              Liebe Grüße

              Kommentar

              Lädt...
              X