4 Stimmen

Effizientes Django QuerySet Regex

Ich habe ein Modell wie dieses:

class CampaignPermittedURL(models.Model):
    hostname = models.CharField(max_length=255)
    path = models.CharField(max_length=255,blank=True)

Regelmäßig bekomme ich eine URL, die ich in einen Hostnamen und einen Pfad aufteilen kann. Was ich möchte, ist, dass der Endbenutzer einen Hostnamen (yahoo.com) und möglicherweise einen Pfad (hochzeiten) eingeben kann.

Ich möchte herausfinden, wann eine URL nicht mit dieser Hostnamen/Pfad-Kombination übereinstimmt, wie folgt:

  • Erfolg: www.yahoo.com/hochzeiten/newyork
  • Erfolg: yahoo.com/hochzeiten
  • Fehlschlag: cnn.com
  • Fehlschlag: cnn.com/hochzeiten

Ich denke, der beste Weg dafür ist:

url = urlsplit("http://www.yahoo.com/hochzeiten/newyork")
### Aufteilen des Hostnamens und des Pfads
matches = CampaignPermittedURL.objects.filter(hostname__regex=r'(com|yahoo.com|www.yahoo.com)'), \
    path__regex=r'(hochzeiten|hochzeiten/newyork)')

Hat jemand bessere Ideen? Ich verwende PostgreSQL und würde ansonsten gerne Django Full Text Search ausprobieren, bin mir aber nicht sicher, ob das sinnvoll ist oder ob es meinen Anforderungen wirklich besser entspricht. Gibt es andere Methoden, die ebenso schnell sind?

Bedenken Sie, dass meine Methode die URL erhält und das CampaignPermittedURL-Objekt möglicherweise viele hundert Datensätze haben kann. Ich suche in erster Linie nach erweiterbaren/wartbaren Lösungen, aber es muss auch effizient sein, da dies auf mehrere hundert Anfrufe pro Sekunde skaliert wird.

Ich habe auch keine Probleme damit, ein anderes Back-End zu verwenden (Sphinx?), aber mir ist es am wichtigsten, möglichst weitgehend bei Standard-Django zu bleiben.

3voto

maček Punkte 72991

Regex: ^(http\:\/\/)?(www\.)?yahoo\.com(\/.+)?$

http://www.yahoo.com/weddings/newyork pass
www.yahoo.com/weddings/foo            pass
www.yahoo.com/weddings                pass
www.yahoo.com                         pass

yahoo.com/weddings/foo                pass
yahoo.com/weddings                    pass
yahoo.com                             pass

cnn.com/weddings/foo                  fail
cnn.com/weddings                      fail
cnn.com                               fail

Regex: ^(http\:\/\/)?(www\.)?yahoo\.com(\/.+)?$

http://www.yahoo.com/weddings/newyork pass
www.yahoo.com/weddings/foo            pass
www.yahoo.com/weddings                pass
www.yahoo.com                         pass

yahoo.com/weddings/foo                pass
yahoo.com/weddings                    pass
yahoo.com                             pass

cnn.com/weddings/foo                  fail
cnn.com/weddings                      fail
cnn.com                               fail

3voto

Adam Nelson Punkte 7612

Ich habe am Ende einen 'verbose' Regex erstellt und den ORM wie in der Frage angegeben verwendet. Das sollte ziemlich schnell sein, ohne von Django abzuweichen:

        # >>> url.hostname.split(".")
    # ["bakery", "yahoo", "com"]
    host_list = url.hostname.split(".")

    # Baue einen Regex wie r"^$|^[.]?com$|^[.]?yahoo\.com$|^[.]?baking[.]yahoo[.]com$"
    # Denke daran, dass
    # >>> r'\'
    # '\\'
    host_list.reverse()

    # append_str2 ist möglicherweise nicht erforderlich
    append_str = r""
    append_str2 = r""
    host_regex = r"^$"
    for host in host_list:
        append_str = r"[.]" + host + append_str
        append_str2 = append_str[3:]
        host_regex = host_regex + r"|^[.]?" + append_str2 + r"$"
    # Wenn überhaupt nichts im Filter ist, umgehe den Filter.
    if CampaignRequiredURL.objects.filter():
        if not CampaignRequiredURL.objects.filter(hostname__iregex=host_regex):
            # Do something based on a hit.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X