如何在 DRF 中搜索多个内容(全文、地理位置等)?

Posted

技术标签:

【中文标题】如何在 DRF 中搜索多个内容(全文、地理位置等)?【英文标题】:How can I do search for multiple things (full-text, geolocation etc) in DRF? 【发布时间】:2019-12-24 01:55:27 【问题描述】:

我在 Django-REST 中有一个模型,它有名称、描述等,以及使用 GeoDjango 的地理定位。现在,我想进行复杂的搜索,在名称和描述字段中进行全文搜索以及地理位置搜索(用户给出位置点和最大距离)。如果需要,我希望它们能够独立工作并一起工作。

我已经了解了如何进行全文搜索(此处:https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/search/)以及如何根据距离进行搜索(此处:https://docs.djangoproject.com/en/2.2/ref/contrib/gis/db-api/)。

到目前为止我的代码(型号,无所谓,只要想名字,描述和位置点):

class SearchAuctions(APIView):
    permission_classes = [AllowAny]

    def get(self, request, format=None):
        """
        Return auctions after filtering.
        """
        items = AuctionItem.objects

        if 'textToSearch' in request.data.keys():
            textToSearch = request.data['textToSearch']
            items = AuctionItem.objects.annotate(
                search=SearchVector('name', 'description'),
            ).filter(search=textToSearch)

        itemSerializer = AuctionItemSerializer(items, many=True)

        return Response(itemSerializer.data)

不确定如何在过滤器之间创建链接。我虽然提出了多个请求并找到了共同的元素,但我猜这太慢了。

【问题讨论】:

您可以应用多个过滤器,例如AuctionItem.objects.filter(search=textToSearch).filter(location=locationToSearch) 这是个好主意,但是如果我不希望某个过滤器发生怎么办?你看到了,我可能有 5 个过滤器,它们可能会发生也可能不会发生。 查询仅在访问时进行评估。因此,您可以从基本查询 items = AuctionItem.objects 开始,然后有条件地向其添加过滤器。例如if searchText: items = items.filter(search=textToSearch)if searchLoc: items = items.filter(...),一旦应用了所有内容,就将其交给序列化程序。 嗯,我知道,只是全文搜索需要注释部分。现在我发现我一开始就可以做到,如果全文搜索不发生也没关系,所以一切都很好。 谢谢,如果您愿意,请为加分写一个正确的答案。 【参考方案1】:

正如我在评论中提到的,您可以将过滤器应用于查询而无需对其进行评估。 这允许您根据条件创建查询,例如

class SearchAuctions(APIView):
    permission_classes = [AllowAny]

    def get(self, request, format=None):
        """
        Return auctions after filtering.
        """
        items = AuctionItem.objects

        if 'textToSearch' in request.data.keys():
            textToSearch = request.data['textToSearch']
            items = items.annotate(
                search=SearchVector('name', 'description'),
            ).filter(search=textToSearch)

        if 'locationToSearch' in request.data.keys():
            locationToSearch = request.data['locationToSearch']
            items = items.filter(location=locationToSearch)

        itemSerializer = AuctionItemSerializer(items, many=True)

        return Response(itemSerializer.data)

【讨论】:

以上是关于如何在 DRF 中搜索多个内容(全文、地理位置等)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FORMSOF 变形全文搜索中获得匹配的位置?

如何使用 QuerySets 和 MySql“全文搜索”在多个字段中进行 Django 搜索?

微信全文搜索技术优化

intellij idea全局搜索

如何优化具有多个结果的 MySQL/MyISAM 全文搜索

Solr 7 - 如何使用地理空间搜索进行全文搜索