gpt4 book ai didi

postgresql - 在 View 中使用全文搜索+GIN(Django 1.11)

转载 作者:行者123 更新时间:2023-11-29 11:42:32 24 4
gpt4 key购买 nike

我需要一些帮助来在 Django View 中构建正确的查询,以便使用 GIN 索引进行全文搜索。我有一个相当大的数据库(约 40 万行),需要对其中的 3 个字段进行全文搜索。尝试使用 django docs search这是 Gin 之前的代码。它有效,但需要 6 秒以上的时间来搜索所有字段。接下来我尝试实现一个 GIN索引以加快我的搜索速度。如何构建它已经有很多问题。但我的问题是 - 当使用 GIN 索引进行搜索时, View 查询会发生什么变化?我应该搜索哪些字段?

在 GIN 之前:

模型.py

class Product(TimeStampedModel):
product_id = models.AutoField(primary_key=True)
shop = models.ForeignKey("Shop", to_field="shop_name")
brand = models.ForeignKey("Brand", to_field="brand_name")
title = models.TextField(blank=False, null=False)
description = models.TextField(blank=True, null=True)

views.py

   
def get_cosmetic(request):
if request.method == "GET":
pass
else:
search_words = request.POST.get("search")
search_vectors = (
SearchVector("title", weight="B")
+ SearchVector("description", weight="C")
+ SearchVector("brand__brand_name", weight="A")
)

products = (
Product.objects.annotate(
search=search_vectors, rank=SearchRank(search_vectors, search)
)
.filter(search=search_words)
.order_by("-rank")
)

return render(request, "example.html", {"products": products})

在 GIN 之后:
模型.py

class ProductManager(models.Manager):
def with_documents(self):
vector = (
pg_search.SearchVector("brand__brand_name", weight="A")
+ pg_search.SearchVector("title", weight="A")
+ pg_search.SearchVector("description", weight="C")
)
return self.get_queryset().annotate(document=vector)


class Product(TimeStampedModel):
product_id = models.AutoField(primary_key=True)
shop = models.ForeignKey("Shop", to_field="shop_name")
brand = models.ForeignKey("Brand", to_field="brand_name")
title = models.TextField(blank=False, null=False)
description = models.TextField(blank=True, null=True)

search_vector = pg_search.SearchVectorField(null=True)

objects = ProductManager()

class Meta:
indexes = [
indexes.GinIndex(
fields=["search_vector"],
name="title_index",
),
]

# update search_vector every time the entry updates
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if (
"update_fields" not in kwargs
or "search_vector" not in kwargs["update_fields"]
):
instance = (
self._meta.default_manager
.with_documents().get(pk=self.pk)
)
instance.search_vector = instance.document
instance.save(update_fields=["search_vector"])

views.py

def get_cosmetic(request):
if request.method == "GET":
pass

else:
search_words = request.POST.get('search')
products = ?????????
return render(request, 'example.html', {"products": products})

最佳答案

回答我自己的问题:

products = (
Product.objects.annotate(rank=SearchRank(F("search_vector"), search_words))
.filter(search_vector=search_words)
.order_by("-rank")
)


这意味着您应该搜索您的索引字段 - 在我的例子中是 search_vector 字段。
此外,我在 ProductManager() 类中稍微更改了我的代码,所以现在我可以使用

products = Product.objects.with_documents(search_words)

其中 with_documents() 是自定义 ProductManager() 的自定义函数。此更改的秘诀是 here (page 29) .

所有这些代码的作用:

  1. 创建带有字段得分的 search_vector,得分越高的字段 - 在结果排序中获得更高的位置。
  2. 通过 ORM Django 创建用于全文搜索的 GIN 索引
  3. 每次更改模型实例时更新 GIN 索引

    此代码不执行的操作:
  4. 它不按查询子串的相关性排序。 Possible solution.

    希望这对在 Django 中进行稍微复杂的全文搜索的人有所帮助。

关于postgresql - 在 View 中使用全文搜索+GIN(Django 1.11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47377947/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com