2010-01-29 8 views
10

Est-il possible de combiner une recherche Django Haystack avec des opérations de filtrage QuerySet "intégrées", en particulier le filtrage avec des instances Q() et des types de recherche non pris en charge par SearchQuerySet? Dans quel ordre:Filtrer Résultats Django Haystack comme QuerySet?

haystack-searched -> queryset-filtered 

ou

queryset-filtered -> haystack-searched 

Parcourir la documentation Django Haystack n'a pas donné de directions comment faire cela.

Répondre

10

Vous pouvez filtrer votre queryset en fonction des résultats d'une recherche Haystack, en utilisant les objets de les PKs:

def view(request): 
    if request.GET.get('q'): 
    from haystack import ModelSearchForm 
    form = ModelSearchForm(request.GET, searchqueryset=None, load_all=True) 
    searchqueryset = form.search() 
    results = [ r.pk for r in searchqueryset ] 

    docs = Document.objects.filter(pk__in=results) 
    # do something with your plain old regular queryset 

    return render_to_response('results.html', {'documents': docs}); 

Je ne sais pas comment cette échelles, mais pour les petits resultsets (quelques centaines, dans mon cas) , ça fonctionne bien.

+6

avec ceci, vos résultats seront triés par ID, et vous perdrez la pertinence. – dzen

+0

@dzen quelle est la meilleure façon de le faire tout en conservant le rang de la pertinence, alors? –

+5

Ce n'est pas à l'échelle. Je suppose que la requête devient trop longue - avec quelques milliers d'identifiants, il n'y aura aucun résultat. –

0

Si vous voulez suivre la pertinence, vous devez accéder à l'objet de la base de données via « objet »:

exemple dans votre modèle:

{% for result in results %} 
    {{ result.object.title }} 
    {{ result.objects.author }} 
{% endfor %} 

Mais ce qui est vraiment mauvais depuis haystack fera une requête supplémentaire comme "SELECT * FROM blah WHERE id = 42" sur chaque résultat.

Vous semblez essayer d'obtenir ces objets de votre base de données parce que vous n'avez pas ajouté de champs supplémentaires dans votre index? Si vous ajoutez le titre et l'auteur dans votre SearchIndex, vous pouvez simplement utiliser vos résultats:

{% for result in results %} 
    {{ result.title }} 
    {{ result.author }} 
{% endfor %} 

et éviter certaines requêtes supplémentaires.

+1

Si vous exécutez searchqueryset.load_all(), les objets seront tous préchargés de la base de données aussi efficacement que possible, au lieu d'un à la fois. – melinath

+0

Avec quelque chose comme "SELECT * FROM bla WHERE id dans (12, 132,1251)" Donc, est-ce efficace, pour ouvrir (peut-être) une nouvelle socket, récupérer des données à partir de là? – dzen

1

De la documentation:

SearchQuerySet.load_all (auto)

Remplit les objets dans Efficacement les résultats de la recherche. Sans utiliser cette méthode, les recherches de base de données sont effectuées sur une base par objet, entraînant de nombreux déplacements individuels vers la base de données. Si load_all est utilisé, le SearchQuerySet regroupe les objets similaires en une seule requête, , ce qui entraîne uniquement autant de requêtes que différents types d'objet renvoyés.

http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#load-all

Par conséquent, une fois que vous avez un SQS filtré, vous pouvez faire un load_all() sur elle et accéder à tout les objets de base de données via SearchResult.object. Par exemple.

sqs = SearchQuerySet() 
# filter as needed, then load_all 
sqs = sqs.load_all() 

for result in sqs: 
    my_obj = result.object 
    # my_obj is a your model object