Ankündigung

Einklappen
Keine Ankündigung bisher.

String-in-String-Suche mit Doctrine

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

  • String-in-String-Suche mit Doctrine

    Hallo miteinander,

    ich habe in einem privaten Projekt eine String-in-String-Suche mit Doctrine geschrieben, die soweit auch funktioniert bzw. meine Anforderungen erfüllt.

    Da man es bei der Arbeit mit Doctrine (bzw. dem QueryBuilder-Objekt) aber eigentlich vermeiden will, sich Query-Strings mit der Low-Level-API zusammen zu tackern und stattdessen eher die High-Level-API mit der Expr-Klasse benutzen sollte (die ich aber wiederum schlecht dokumentiert finde), wollte ich einmal in die Runde fragen, ob jemand von euch einen Ansatz hat, das Ganze eleganter oder sauberer zu lösen oder ob man das so wie unten zu sehen machen kann.

    Hier findet ihr daher den entsprechenden Code aus einer Methode eines meiner Repositories:

    PHP-Code:
    $tags $article->getTagsArray();
    $queryString '';

    $qb $this->createQueryBuilder('a')
                 ->
    distinct()
                 ->
    where('a.id != :id')
                 ->
    setParameter('id'$article->getId())
                 ->
    andWhere('a.articleType = :articleType')
                 ->
    setParameter('articleType'$article->getArticleType());

    for (
    $i 0$i count($tags); $i++) {

        
    $queryString .= 'LOCATE(:tag' $i ', a.tags) > 0';
        
    $qb->setParameter('tag' $i$tags[$i]);

        if (
    $i count($tags)) {

            
    $queryString .= ' OR ';
        }
    }

    return 
    $qb->andWhere($queryString)
                 ->
    andWhere('a.active = true')
                 ->
    addOrderBy('a.id''DESC')
                 ->
    setMaxResults(5)
                 ->
    getQuery()
                 ->
    getResult(); 


  • #2
    Bring das Datenbankdesign in Normalform und du hast eine saubere Abfrage (JOIN und im WHERE ein IN).
    PHP-Code:
    ...->andWhere($qb->expr()->in('x.tags'':tags'))
                  ->
    setParameter('tags'$tags); 
    Damit gehst du auch Problemen aus den weg wie "Auto", "Autobahn". Bei deinem Ansatz matcht Auto auch Autobahn.

    Kommentar


    • #3
      Vielen Dank für deine Antwort, dieser Ansatz macht natürlich Sinn - Normalisierung ist mir natürlich auch ein Begriff.

      Ich habe meinen Ansatz jedoch gewählt, da die Datensätze matchen sollen, sobald eines der n Tags eines Artikels in den n Tags des anderen Artikels vorkommt.

      Wenn ich micht nicht täusche matcht dein Ansatz jedoch nur wenn alle n Tags beider Artikel deckungsgleich sind, oder?

      Kommentar


      • #4
        Nein, das ist eine ODER Verknüpfung. Der umgedrehte Fall wäre in der Normalform sogar relativ aufwendig.

        Kommentar


        • #5
          Danke schön noch einmal für den Hinweis, ich habe dieses WE ein wenig Zeit gefunden, um das ganze zu normalisieren und dementsprechend umzubauen.

          Ich ärgere mich aber ein klein wenig, da ich es eigentlich besser weiß bzw. besser hätte wissen müssen. Die Zeit, die ich darauf verwendet habe, in der Doctrine-Doku und auf Stackoverflow zu suchen und zu lesen, um mir einen Query zu schreiben, der im Endeffekt sogar falsch matched und dadurch falsche Ergebnisse liefert, hätte ich mir eigentlich sparen können, um es gleich richtig zu machen.

          Aber das "angelernte" Streben nach Effizienz ("schnell, schnell, Hauptsache es läuft irgendwie...") hat dies wohl verhindert (Datenmodell und Logik der ersten Variante, nämlich mehrere Werte in einem String zu speichern und die Serialisierung / Deserialisierung waren bis auf den Query tatsächlich extrem schnell gemacht).

          Es soll ja im Berufsleben in relativ großen Projekten auch zur von der Projektleitung vorgegebenen "Best Practice" gehören, bspw. Telefonnummern oder die Rollen des Security-Systems eines Frameworks auf diese Art und Weise in der DB zu speichern.

          Da ich meine, zumindest das mit den Rollen des Security Systems auch einmal in der Doku oder in einem Tutorial so gelesen zu haben, wollte ich abschließend einmal in die Runde fragen, ob ihr Situationen seht, wo man so etwas (absichtliches Verletzen der Normalformen o.ä.) tatsächlich machen kann und es eher hilfreich als schädlich ist, oder geht das grundsätzlich gar nicht?

          Kommentar

          Lädt...
          X