2013-05-22 2 views
1

Comment filtrer/rejoindre un Haystack SearchQuerySet par des champs de modèles liés?Comment filtrer Haystack SearchQuerySets par modèles connexes

J'ai une requête comme:

sqs = SearchQuerySet().models(models.Person) 

et cela renvoie les mêmes résultats que l'équivalent retourne page d'administration.

Cependant, si je tente et filtrer par les enregistrements des modèles liés par une clé étrangère:

sqs = sqs.filter(workplace__role__name='teacher') 

il ne renvoie rien, même si la page /admin/myapp/person/?workplace__role__name=teacher revient plusieurs enregistrements.

Je ne souhaite effectuer aucune recherche de texte intégral sur ces modèles associés. Je veux seulement faire un simple filtre exact. Est-ce possible avec Haystack?

Répondre

5

Vous ne pouvez pas effectuer de jointures à l'aide d'un moteur de recherche comme ceux pris en charge par haystack. Pour faire des requêtes telles que vous devez ajouter les informations que vous souhaitez filtrer de façon « dénormaliser » dans l'index de recherche:

class ProfileIndex(indexes.SearchIndex, indexes.Indexable): 
    # your other fields, most likely model attributes 
    role_name = indexes.CharField() 

    def get_model(self): 
     return Person 

    def prepare_role_name(self, person): 
     return person.workplace.role_name 

Ensuite, vous pouvez filtrer sur un champ role_name. Assurez-vous simplement de mettre à jour votre index si par exemple. le nom change, vous devez alors mettre à jour toutes les entrées correspondantes dans l'index de recherche.

+0

Votre exemple spécifique n'a pas de sens, car le lien personne-> lieu de travail est une relation un-à-plusieurs. – Cerin

+0

Eh bien, c'est ainsi que fonctionnent ces moteurs de recherche ... D'un autre côté, l'accès à ces informations dénormalisées est très rapide car vous n'avez pas besoin d'effectuer d'autres recherches/jointures pour y accéder. Si vous évitez de cliquer sur votre base de données lors de l'affichage des résultats de recherche, vous pouvez avoir un grand avantage de performance ... Voir aussi http://django-haystack.readthedocs.org/en/latest/best_practices.html#avoid-hitting-the- base de données –

+0

Ne connaissez pas votre disposition exacte des données ... Vous pouvez faire la même chose que ci-dessus avec une relation un à plusieurs, en utilisant 'MultiValueField' de haystack qui peut contenir une liste (et que vous pouvez filtrer pour des valeurs uniques). Voir cet article https://gist.github.com/cooncesean/2892533 –

0

Vous pouvez aussi le faire:

class ProfileIndex(indexes.SearchIndex, indexes.Indexable): 
    # your other fields, most likely model attributes 
    role_name = indexes.CharField(model_attr='workplace__role__name') 

    def get_model(self): 
     return Person 

Et vous pouvez filtrer par role_name. Je l'ai vu ici.

Questions connexes