简短的问题:中是否有一种方法可以根据某个字段的字母顺序,以不区分大小写的方式找到下一行?
长问题:--我在数据库中有一些单词,以及它们的详细视图。我希望能够按字母顺序浏览这些单词。所以我需要按字母顺序找出前一个和下一个单词的id。现在,我所做的工作如下(原始字段是存储单词名称的字段):
class Word(models.Model):
original = models.CharField(max_length=50)
...
def neighbours(self):
"""
Returns the words adjacent to a given word, in alphabetical order
"""
previous_words = Word.objects.filter(
original__lt=self.original).order_by('-original')
next_words = Word.objects.filter(
original__gt=self.original).order_by('original')
previous = previous_words[0] if len(previous_words) else None
next = next_words[0] if len(next_words) else None
return previous, next问题是,这做了区分大小写的比较,所以Foo出现在bar之前,这不是我想要的。为了避免这个问题,在另一个视图中,我列出了所有单词,我使用了一个自定义模型管理器,它添加了一个额外的字段,如下所示
class CaseInsensitiveManager(models.Manager):
def get_query_set(self):
"""
Also adds an extra 'lower' field which is useful for ordering
"""
return super(CaseInsensitiveManager, self).get_query_set().extra(
select={'lower': 'lower(original)'})在单词的定义中,我添加
objects = models.Manager()
alpha = CaseInsensitiveManager()通过这种方式,我可以执行如下的查询
Word.alpha.all().order_by('lower')把所有单词按字母顺序排列,不管情况如何。但我做不到
class Word(models.Model):
original = models.CharField(max_length=50)
...
objects = models.Manager()
alpha = CaseInsensitiveManager()
def neighbours(self):
previous_words = Word.objects.filter(
lower__lt=self.lower()).order_by('-lower')
next_words = Word.objects.filter(
lower__gt=self.lower()).order_by('lower')
previous = previous_words[0] if len(previous_words) else None
next = next_words[0] if len(next_words) else None
return previous, next事实上,Django不会接受基于字段查找的额外字段。那么,我应该做什么(除了编写自定义SQL)?
奖金问题:,至少我看到了我正在做的事情中的更多问题。首先,我对表演不太确定。我假设在定义previous_words和next_words时根本不执行查询,而在定义previous和next时,数据库中的唯一查找将发生,从而产生或多或少的查询。
SELECT Word.original, ..., lower(Word.original) AS lower
WHERE lower < `foo`
ORDER BY lower DESC
LIMIT 1是这样的吗?还是我做了什么会使数据库太慢的事情?关于Django ORM的内部工作,我不知道足够的细节。
第二个问题是,我实际上不得不用不同的语言来处理单词。考虑到我知道每个单词的语言,是否有办法使它们按字母顺序排列,即使它们有非ASCII字符。例如,我希望méchant,moche按这个顺序排列,但是我得到了moche,méchant。
发布于 2011-04-22 16:51:53
数据库应该能够为您进行这种排序,并且它应该能够这样做,而不需要“低级”函数。
实际上,您需要修复的是数据库排序和编码。
例如,如果使用mysql,可以使用字符集utf8和排序规则utf8_general_ci。
如果该排序规则不适用于您,则可以根据您的需要和数据库尝试其他排序规则。但是在查询中使用一个额外的字段和一个函数是一个丑陋的解决方法,它会减缓应用程序的速度。
mysql和postgresql中也有许多排序规则选项可用:
http://dev.mysql.com/doc/refman/5.5/en/charset-mysql.html http://stackoverflow.com/questions/1423378/postgresql-utf8-character-comparison
但这绝对是在db级别进行优化的好机会。
https://stackoverflow.com/questions/5756158
复制相似问题