Ankündigung

Einklappen
Keine Ankündigung bisher.

Volltextsuche in Spalte (Hashtags in Spalte suchen)

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

  • Volltextsuche in Spalte (Hashtags in Spalte suchen)

    Hallo Zusammen,

    ich habe bereits recherchiert und leider keine passende Antwort gefunden.

    Ich habe eine Tabelle: Notiz mit folgenden Spalten (id, text, createdBy).

    Die ID wird automatisch hochgezählt.
    Der Text besteht aus einem Text in dem Hashtags (ggf. auch mehrere) vorkommen (Beispiel: Dies ist mein Text und #meinHashtag vielleicht gibt es noch einen #weiterenHashtag).
    createdBy: User ID des Users der den Eintrag erstellt hat.

    Zudem habe ich eine Tabelle: Hashtag in der alle angelegten Hashtags festgehalten sind:
    hashtag: #meinHashtag

    Nun würde ich gerne alle Hashtags zum User ausgeben.

    In diesem Fall wäre es, für das Beispiel oben:
    #meinHashtag
    #weiterenHashtag

    Dies scheint sich prinzipiell einfach über LIKE lösen zu lassen:

    SELECT * FROM hashtag
    INNER JOIN notes ON
    notes.text LIKE CONCAT('%#',hashtag.hashtag,'%')
    AND notes.createdby = :userID
    GROUP BY hashtag.hashtag

    Leider wird hier eben nun auch ein

    #abc
    in einem
    #abcdef

    gefunden.

    Ich habe es bereits mit REGEX versucht und auch mit der Volltextsuche. Leider konnte ich dies für diese Suchanfrage nicht erfolgreich umsetzen:

    - Die Volltextsuche kann gezielt nach einem Hashtag erfolgreich suchen, sobald ich nun mehrere Hashtags übergeben will, scheitert es
    - REGEX hat trotz korrekten Regulären Ausdruck nicht funktioniert.

    Hat mir jemand einen Tipp?

    Danke und Gruß


  • #2
    Falsches Datenbankdesign. In einer Spalte sollte nicht mehr als ein Wert stehen. Du brauchst eine zusätzliche Tabelle für die Hashtags.

    Außerdem ist SELECT * böse und sollte nicht verwendet werden. Und im GROUP BY sollten alle Spalten stehen, die auch im SELECT ausgewählt werden.

    Kommentar


    • #3
      Hi Hellbringer,

      okay danke für die Antwort. Der SELECT * sowie das ungenaue Group By hab ich lediglich hier im Forum im Beispiel verwendet, aber danke für den Hinweis.

      Hier eine aktualisierte Version:

      Code:
      SELECT hashtag.hashtag FROM hashtag
      INNER JOIN notes ON
      notes.text LIKE CONCAT('%#',hashtag.hashtag,'%')
      AND notes.createdby = :userID
      GROUP BY hashtag.hashtag

      Du hast natürlich Recht in einer Spalte sollte nicht mehr als ein Wert stehen.. aber wie würdest Du das für Hashtags realisieren?
      Würdest Du diese vom Text entkoppeln?

      Aktuell wird mir ein Hashtag an einer beliebigen Position im Text angezeigt:
      Dies ist #meinHashtag .. und hier hab ich nochmal einen #hashtag

      Wie erwähnt, hab ich eine zusätzliche Tabelle für Hashtags, diese haben jedoch keinerlei Relation zur Tabelle: notes.

      Viele Grüße

      Kommentar


      • #4
        Bitte Code-Tags hier im Forum nutzen. Danke!
        Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
        PHP.de Wissenssammlung | Kein Support per PN

        Kommentar


        • #5
          Du brauchst noch eine Tabelle mit der Relation von Id hashtags zu Id notes.

          Im Prinzip so ähnlich
          Tabelle notes_to_hashtags
          Code:
          id    id_notes    id_hashtags
          -----------------------------
          ...
          234   12          2
          235   12          5
          236   12          7
          237   13          2
          usw.
          Wenn du nun nach #myHashtag suchst und dieser in der hastag Tabelle die Nummer 2 hat, dann kannst du in dieser Tabelle die zugehörigen Notes finden.

          Kommentar


          • #6
            Servus Protestix,

            danke für die Information.

            Ich bin damals der Relation aus dem Weg gegangen, da ein erhöhter Aufwand beim Löschen / Ändern von hashtags entsteht. Hier wollte ich das ganze "Keep it simple" halten.
            Dies würde auch klappen, wenn ich gezielt nach #TAG in einer VARCHAR- Spalte suchen könnte.

            Die Lösung mit einer Relations- Tabelle ist aus erster Sicht performanter, zieht jedoch den Prozess der Verwaltung von gelöschten / geänderten Hashtags in Notes nach.

            Gibt es noch weiter Denkansätze / Lösungen / Vorschläge?

            Viele Grüße

            Kommentar


            • #7
              Kommt drauf an, welches Datenbanksystem du verwendest. Es gibt welche, die auch mit serialisierten Werten performant umgehen können (z.B. PostegreSQL oder MSSQL). Hier könntest du die Werte z.B. als JSON speichern. MySQL ist da sehr eingeschränkt und eher unbrauchbar.

              Kommentar


              • #8
                Zitat von gnewmann Beitrag anzeigen
                - Die Volltextsuche kann gezielt nach einem Hashtag erfolgreich suchen, sobald ich nun mehrere Hashtags übergeben will, scheitert es
                Woran scheitert es denn? Du kannst mehrere match/against mit OR verknüpfen. Das Problem könnte eher sein (bin ich mir nicht sicher -> testen) das du mit #blub auch Texte findest die das Wort blub enthalten.

                Kommentar


                • #9
                  Zitat von erc Beitrag anzeigen

                  Woran scheitert es denn? Du kannst mehrere match/against mit OR verknüpfen. Das Problem könnte eher sein (bin ich mir nicht sicher -> testen) das du mit #blub auch Texte findest die das Wort blub enthalten.
                  Ich würde gerne alle Ergebnisse aus einem Select auf die Hashtag- Tabelle mit dem match/against verknüpfen.
                  Dies ist mir leider nicht gelungen.

                  Eine "Or" - Bedingung auf jeden Hashtag aus der Hashtag- Tabelle müsste ich über den Programmcode zusammenbauen, das würde stark zu Schulden der Performance und Einfachheit (Keep it simple) gehen.

                  Kommentar


                  • #10
                    Zitat von hellbringer Beitrag anzeigen
                    Kommt drauf an, welches Datenbanksystem du verwendest. Es gibt welche, die auch mit serialisierten Werten performant umgehen können (z.B. PostegreSQL oder MSSQL). Hier könntest du die Werte z.B. als JSON speichern. MySQL ist da sehr eingeschränkt und eher unbrauchbar.
                    Ich verwende bei diesem Thema MySQL. Aber gut zu Wissen das serialisierte Werte in Postgres und MSSQL performante Lösungen darstellen.

                    Kommentar


                    • #11
                      ich würde noch ARRAY in PostgreSQL nennen - die kann man indexbased durchsuchen - also sehr schnell und effektiv. Aber gut, wer lieber sportlich ist und mit primitiven Mitteln zum Ziel kommen will, ...
                      PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                      Kommentar


                      • #12
                        Gut ich muss umformulieren, ich arbeite bei diesem Projekt bereits mit MySQL
                        Ein Umzug auf eine andere Datenbank wegen den Hashtags wäre (aus meiner Sicht) nicht sinnvoll.
                        Es ist sicherlich auch eine Frage der Datenmenge und Komplexität (die hier sehr überschaubar ist).

                        Die Lösung mit der Zwischentabelle ist sicherlich der richtige Ansatz, den ich weiter verfolgen werde (Stichwort: Normalisierung).

                        Um jedoch auf die ursprüngliche Frage zurückzukommen:

                        Kennt jemand eine Möglichkeit nach einem Hashtag / einer definierten Zeichenfolge in MySQL zu suchen?
                        Zu beachten gilt, es sollen folgende Suchen erfolgreich ablaufen:

                        This is my #hashtag
                        #hashtag here we go
                        Hello #hashtag how are u?

                        This is my #hashtagAddition <-- sollte 'nicht' gefunden werden

                        Kommentar


                        • #13
                          This is my #hashtag
                          #hashtag here we go
                          Hello #hashtag how are u?

                          This is my #hashtagAddition <-- sollte 'nicht' gefunden werden
                          In Regex macht man das mit \b für Boundaries (zB: https://regex101.com/r/f4oEy9/1 ) Schau mal ob das die RegexSyntax von Mysql kann.


                          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                          PHP.de Wissenssammlung | Kein Support per PN

                          Kommentar


                          • #14
                            Zitat von gnewmann Beitrag anzeigen
                            Eine "Or" - Bedingung auf jeden Hashtag aus der Hashtag- Tabelle müsste ich über den Programmcode zusammenbauen, das würde stark zu Schulden der Performance und Einfachheit (Keep it simple) gehen.
                            Das ist Bullshit. Den Query zu erzeugen kostest im Verhältnis zum ausführen nix. Ich hab dein Problem aber auch falsch verstanden. Das ist von hinten durch die Brust ins Auge. Der Ansatz skaliert nicht. Wenn es nicht skalieren muss, kannst du den LIKE Part in deinem Query gegen das MATCH/AGAINST ersetzten. (das ist durch den JOIN dann genau so als würdest du für jeden Hashtag OR schreiben) Alternativ kannst du auch mit RLIKE arbeiten, da kannst du mit [[:>:]] ein Wrodboundary matchen.

                            PHP-Code:
                            notes.text RLIKE CONCAT('#',hashtag.hashtag,'[[:>:]]'
                            Der Variante mit den Volltextindex ist hier aber performanter!

                            Kommentar


                            • #15
                              Zitat von erc Beitrag anzeigen

                              Das ist Bullshit. Den Query zu erzeugen kostest im Verhältnis zum ausführen nix. Ich hab dein Problem aber auch falsch verstanden. Das ist von hinten durch die Brust ins Auge. Der Ansatz skaliert nicht. Wenn es nicht skalieren muss, kannst du den LIKE Part in deinem Query gegen das MATCH/AGAINST ersetzten. (das ist durch den JOIN dann genau so als würdest du für jeden Hashtag OR schreiben) Alternativ kannst du auch mit RLIKE arbeiten, da kannst du mit [[:>:]] ein Wrodboundary matchen.

                              PHP-Code:
                              notes.text RLIKE CONCAT('#',hashtag.hashtag,'[[:>:]]'
                              Der Variante mit den Volltextindex ist hier aber performanter!
                              Das Wordboundary hat funktioniert. Danke.
                              MATCH/AGAINST ignoriert das Hashtag- Zeichen.

                              Kannst Du mir einen skalierbaren Ansatz nennen?

                              Kommentar

                              Lädt...
                              X