Эффективное регулярное выражение Django QuerySet - PullRequest
4 голосов
/ 08 октября 2009

У меня есть такая модель:

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

Чаще всего мне вручают URL-адрес, который я могу URL-адресом разделить на имя хоста и путь. Мне бы хотелось, чтобы конечный пользователь мог ввести имя хоста (yahoo.com) и, возможно, путь (свадьбы).

Я бы хотел найти, когда URL не «совпадает» с этой комбинацией имени хоста / пути, например:

  • успех: www.yahoo.com/weddings/newyork
  • успех: yahoo.com/weddings
  • отказ: cnn.com
  • ошибка: cnn.com/weddings

Я думаю, что лучший способ сделать это:

url = urlsplit("http://www.yahoo.com/weddings/newyork")
### split hostname on . and path on /
matches = CampaignPermittedURL.objects.filter(hostname__regex=r'(com|yahoo.com|www.yahoo.com)'), \
    path__regex=r'(weddings|weddings/newyork)')

У кого-нибудь есть идеи получше? Я использую PostgreSQL и в противном случае хотел бы попробовать Полнотекстовый поиск Django , но я не уверен, стоит ли это того или он действительно лучше моих. Существуют ли другие методы, которые одинаково быстры?

Имейте в виду, что моему методу передан URL-адрес и что объект CampaignPermittedURL может иметь много сотен записей. В первую очередь я ищу расширяемые / поддерживаемые решения, но они также должны быть эффективными, поскольку это будет масштабироваться до нескольких сотен вызовов в секунду.

Я тоже в порядке с использованием другого бэк-энда ( Sphinx ?), Но меня больше всего беспокоит возможность оставаться со стандартным Джанго в максимально возможной степени.

Ответы [ 2 ]

3 голосов
/ 12 октября 2009

Я закончил тем, что создал «подробное» регулярное выражение и использовал ORM, как указано в вопросе. Это должно быть довольно быстро, не отходя от Джанго:

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

    # Build regex like r"^$|^[.]?com$|^[.]?yahoo\.com$|^[.]?baking[.]yahoo[.]com$"
    # Remember that
    # >>> r'\'
    # '\\'
    host_list.reverse()

    # append_str2 might not be necessary
    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"$"
    # If nothing is in the filter at all, bypass the filter.
    if CampaignRequiredURL.objects.filter():
        if not CampaignRequiredURL.objects.filter(hostname__iregex=host_regex):
            #Do something based on a hit.
3 голосов
/ 08 октября 2009

Регулярное выражение: ^(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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...