我很高兴在GAE上构建了几个简单的应用程序,但现在我对如何在应用程序引擎上构建音乐收藏组织者感到困惑。简而言之,我无法弄清楚在排序另一个属性时如何过滤多个属性。
我们假设核心模型是一个包含多个属性的相册,包括:
我们还假设我想使用这些属性过滤整个集合,然后按以下方法之一对结果进行排序:
我不知道如何在不遇到爆炸式索引难题的情况下做到这一点。具体来说,我喜欢做类似的事情:
Albums.all().filter('publication_year <', 1980).order('artist_name')
我知道这是不可能的,但是解决方法是什么?
这似乎是一种相当普遍的应用程序。音乐专辑可以是餐馆,葡萄酒或酒店。我有一系列具有描述性属性的项目,我想对其进行过滤和排序。
我是否有俯瞰的最佳实践数据模型设计?有什么建议吗?
答案 0 :(得分:1)
这里有几个选项:您可以尽可能地过滤,然后按照Alex的建议在内存中对结果进行排序,或者您可以为等式过滤器而不是不等式过滤器重新设计数据结构。
例如,假设您只想过滤十年,您可以添加一个字段来编码录制歌曲的十年。要在十年之前或之后查找所有内容,请执行您想要跨越几十年的IN查询。这将需要每十年包含一个基础查询,但如果记录数量很大,这仍然比获取所有结果并在内存中排序更便宜。
答案 1 :(得分:1)
由于存储很便宜,您可以使用反映排序条件的key_names创建自己的基于ListProperty的索引文件。
class album_pubyear_List(db.Model):
words = db.StringListProperty()
class album_length_List(db.Model):
words = db.StringListProperty()
class album_artist_List(db.Model):
words = db.StringListProperty()
class Album(db.Model):
blah...
def save(self):
super(Album, self).save()
# you could do this at save time or batch it and do
# it with a cronjob or taskqueue
words = []
for field in ["title", "artist", "label", "genre", ...]:
words.append("%s:%s" %(field, getattr(self, field)))
word_records = []
now = repr(time.time())
word_records.append(album_pubyear_List(parent=self, key_name="%s_%s" %(self.pubyear, now)), words=words)
word_records.append(album_length_List(parent=self, key_name="%s_%s" %(self.album_length, now)), words=words)
word_records.append(album_artist_List(parent=self, key_name="%s_%s" %(self.artist_name, now)), words=words)
db.put(word_records)
现在是时候搜索了你创建一个合适的WHERE子句并调用适当的模型
where = "WHERE words = " + "%s:%s" %(field-a, value-a) + " AND " + "%s:%s" %(field-b, value-b) etc.
aModel = "album_pubyear_List" # or anyone of the other key_name sorted wordlist models
indexes = db.GqlQuery("""SELECT __key__ from %s %s""" %(aModel, where))
keys = [k.parent() for k in indexes[offset:numresults+1]] # +1 for pagination
object_list = db.get(keys) # returns a sorted by key_name list of Albums
答案 2 :(得分:0)
正如你所说,你不能在一个领域和另一个领域的顺序(或两个领域的不等,等等)上存在不等式条件。解决方法只是使用“最佳”不等式条件来获取内存中的数据(其中“最佳”表示预期会产生最少数据的数据),然后进一步优化它并在应用程序中通过Python代码对其进行排序。
Python的列表推导(以及其他形式的循环&amp; c),列表的sort
方法和sorted
内置函数,标准库中的itertools
模块等等on,所有这些都有助于使这些任务在Python本身中非常简单。