2017-11-19 29 views
0

GINインデックスを使用した全文検索のためのdjangoビューで適切なクエリを構築するための助けが必要です。私はかなり大きなデータベース(〜400k行)を持っており、そこから3つのフィールドでフルテキスト検索を行う必要があります。 django docs searchを使用しようとしました。これはGEFのコードです。それは動作しますが、すべてのフィールドを検索するのに6秒以上かかります。次に、検索を高速化するためにGINインデックスを実装しようとしました。既にそれを構築する方法にはたくさんの質問があります。しかし、私の質問は - 検索のためのGINインデックスを使用すると、どのようにビューのクエリが変更されますか?検索するフィールドは何ですか?

models.pyビューでの全文検索+ GINの使用(Django 1.11)

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後::GIN前


models.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}) 

答えて

0

自分の質問に答える:

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


これはあなたのインデックスフィールドを検索することを - に私の場合search_vectorフィールド。
はまた、私は)ので、今、私はちょうどwith_documents()は、カスタムプロダクトマネージャー(のカスタム関数である

products = Product.objects.with_documents(search_words) 

を使用することができ、ビットプロダクトマネージャー()クラスで自分のコードを変更しました。この変更のレシピはhere (page 30)です。


1)スコアにフィールドを追加したsearch_vectorを作成します。スコアが大きいフィールドは、結果の並べ替えで高い位置になります。
1)それはソートしません:
2)ORMジャンゴ
3を経由して、フルテキスト検索のためのGINインデックスを作成する)は、モデルのインスタンスが
このコードが実行するdosn't何
を変更するたびにGINインデックスを更新します照会される部分文字列の関連性によってPossible solution.

これは、Djangoで少し複雑な全文検索で誰かを助けることを願っています。