在Django中高效地搜索外键树

在Django中高效地搜索外键树,django,orm,Django,Orm,我使用ForeignKey从模型中创建了一个树状结构 联系。例如: Model Person: name = CharField Model Book: name = CharField author = FK(Person) Model Movie: name = CharField director = FK(Person) Model Album: name = CharField director =

我使用ForeignKey从模型中创建了一个树状结构 联系。例如:

Model Person:  
   name = CharField  

Model Book:  
   name = CharField  
   author = FK(Person)  

Model Movie:  
   name = CharField  
   director = FK(Person)  

Model Album:  
   name = CharField  
   director = FK(Person)  

Model Chapter:  
   name = CharField  
   book = FK(Book)  

Model Scene:  
   name = CharField  
   movie = FK(Movie)  

Model Song:  
   name = CharField  
   album = FK(Album)  
这里需要注意的是,真正的结构既深又广,而且 节点可能有多个非FK字段,即不仅仅是“名称”

我想做的是有一个搜索函数,这样就有一个字符串 提供,它将返回与Person对象匹配的任何Person 本身,或任何子节点中的字段。瞧,如果被打败了,那就是 字符串,以及与相册关联的歌曲的名称 人员匹配时,将返回该人员

到目前为止,我所做的工作如下:

对于任何叶节点,都有一个带有搜索方法的管理器对象 比如:

return Song.objects.filter(name__icontains=search_string)
class AlbumManager(models.Model):  
    def search(self, search_string):  
        from_songs = Album.objects.filter(song__in=Song.objects.search(search_string))  
        return Album.objects.filter(name__icontains=search_string)|from_songs  
然后对于根节点Person和任何内部节点,还有一个 带有搜索方法的管理器对象,该搜索方法类似于:

return Song.objects.filter(name__icontains=search_string)
class AlbumManager(models.Model):  
    def search(self, search_string):  
        from_songs = Album.objects.filter(song__in=Song.objects.search(search_string))  
        return Album.objects.filter(name__icontains=search_string)|from_songs  
正如您所想象的,一旦到达根节点,就会释放一个 大量的查询,而且效率很低。我会很漂亮的 如果没有更好的方法,我会很惊讶。。。一个想法是 在树的顶部有一个手动搜索的搜索方法 通过一切,但一个看起来很混乱,虽然可能更多 高效和b最好能够搜索单个节点 武断地

这么说来,有什么更有效的方法可以获得
我想去哪里而不是我的白痴方法

也许最好将搜索功能外包给一个专门的工具,如or。两个搜索框架都有项目,分别与Django和Django集成。与使用包含许多联接和子查询的复杂SQL查询相比,您将获得更好的性能。

也许最好将搜索功能外包给专用工具,如or。两个搜索框架都有项目,分别与Django和Django集成。与使用包含多个联接和子查询的复杂SQL查询相比,您将获得更好的性能。

是另一种选择。

是另一种选择。

我认为使用基本ORM所能做的任何事情都不会真正有效,基本上,您将在具有大量连接的不同模型上运行一系列过滤器查询

如果您的目标是高性能、长期的解决方案,那么最好的办法就是在内存中创建一个对象存储库。我认为在基本SQL中没有任何方法可以使这些查询高效,特别是当您处理大量行时


为您的子对象章节、歌曲等创建一个非规范化的表,其中包含您的所有个人和书籍/专辑数据,这可能是一个潜在的中期解决方案,这将需要一些奇特的SQL基础工作,这可能不是Django Core的一部分。

我认为您可以用基本ORM做的任何事情都不会真正有效,基本上,您将在具有大量连接的不同模型上运行一系列过滤器查询

如果您的目标是高性能、长期的解决方案,那么最好的办法就是在内存中创建一个对象存储库。我认为在基本SQL中没有任何方法可以使这些查询高效,特别是当您处理大量行时


为您的子对象章节、歌曲等创建一个非规范化的表,其中包含您的所有个人和书籍/专辑数据,这可能是一个潜在的中期解决方案,这将需要一些花哨的SQL步法,这可能不是Django Core的一部分。

好吧,如果您不想设置像whoosh这样的搜索引擎,那么您可以使用Q

这需要对字段进行一点硬编码,而不是简单地遍历所有字段

>>> q = Q()
>>> q = q | Q( fk__fk__field__icontains = searchTerm )
>>> q = q | ...
...
>>> qs = Model.objects.filter(q)

好吧,如果你不想建立像whoosh这样的搜索引擎,那么你可以使用Q

这需要对字段进行一点硬编码,而不是简单地遍历所有字段

>>> q = Q()
>>> q = q | Q( fk__fk__field__icontains = searchTerm )
>>> q = q | ...
...
>>> qs = Model.objects.filter(q)

我考虑过反规范化,但不幸的是,我真的没有能力在数据库的这一部分对表结构进行篡改。我想基本的Django ORM不会有太好的选择。是的,去规范化对Django来说是陌生的,事实上,尽管ORM很简单,但它也存在一些超大规模的性能问题,特别是如果你想进行复杂的搜索。看看卡尔·亨德森在DjangoCon的主旨演讲,他谈到了其中的一些事情。对于任何使用Django的人来说,这都是一个很好的听力工具。谢谢你的指点。对我来说,ORM对我来说是一个积极的因素-DB本身对于ORM来说是次优的,但是总体流量太低,以至于它平衡了,在一些地方我不使用ORM。。。考虑到这让我的生活轻松多了,我还是要接受它这恰好是我遇到的问题之一。我考虑过反规范化,但不幸的是,我没有能力在这一部分中对表结构进行修改
DB的一部分。我想基本的Django ORM不会有太好的选择。是的,去规范化对Django来说是陌生的,事实上,尽管ORM很简单,但它也存在一些超大规模的性能问题,特别是如果你想进行复杂的搜索。看看卡尔·亨德森在DjangoCon的主旨演讲,他谈到了其中的一些事情。对于任何使用Django的人来说,这都是一个很好的听力工具。谢谢你的指点。对我来说,ORM对我来说是一个积极的因素-DB本身对于ORM来说是次优的,但是总体流量太低,以至于它平衡了,在一些地方我不使用ORM。。。考虑到这让我的生活轻松多了,我还是要接受它这恰好是一个问题。我一直在研究Woosh和Sphinx,它们似乎都比Solr容易设置,虽然我当前的设置太慢,但我不需要超高性能。我一直在研究Woosh和Sphinx,它们似乎都比Solr容易设置,虽然我当前的设置太慢,但我不需要超高性能。哪种感觉更容易处理?这基本上就是我正在做的。一旦它开始变得非常深入,我就开始在每一层封装一个迷你搜索,当你向树的根移动时,Q调用涉及到其他搜索方法。只需在根级别执行Q并手动进入fk,速度更快,但仍然相当粗糙。这基本上就是我正在做的。一旦它开始变得非常深入,我就开始在每一层封装一个迷你搜索,当你向树的根移动时,Q调用涉及到其他搜索方法。只是在根级别执行Q并手动进入fk的速度更快,但仍然相当粗糙。