2010-01-29 28 views
10

Czy możliwe jest łączenie wyszukiwania Django Haystack z "wbudowanymi" operacjami filtrowania QuerySet, w szczególności filtrowanie przy użyciu instancji Q() i typów wyszukiwania nieobsługiwanych przez SearchQuerySet? W dowolnej kolejności:Filtr Django Haystack wyniki jak QuerySet?

haystack-searched -> queryset-filtered 

lub

queryset-filtered -> haystack-searched 

Przeglądając dokumentację Django Haystack nie daje żadnych wskazówek, jak to zrobić.

Odpowiedz

10

Można filtrować queryset na podstawie wyników wyszukiwania stogu siana, używając PKs obiektów:

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}); 

Nie wiem, jak to skaluje, ale dla małych wynikowych (kilkaset, w moim przypadku) działa to dobrze.

+6

z tym, twoje wyniki zostaną posortowane według identyfikatorów, a stracisz trafność. – dzen

+0

@doc jaki jest najlepszy sposób, aby to zrobić, zachowując jednocześnie stopień trafności? –

+5

To nie jest skalowane. Zakładam, że zapytanie będzie zbyt długie - z kilkoma tysiącami ids będzie 0 wyników. –

0

Jeśli chcesz być na bieżąco z zasadnością, trzeba uzyskać dostęp do obiektu z bazy danych przez „obiekt”:

przykład w szablonie:

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

Ale to jest naprawdę źle, ponieważ haystack dostarczy dodatkową prośbę, taką jak "SELECT * FROM blah WHERE id = 42" na każdym wyniku.

Wygląda na to, że próbujesz pobrać te obiekty z bazy danych, ponieważ nie wstawiłeś dodatkowych pól do indeksu? Jeśli dodać tytuł i autor w swojej SearchIndex, wtedy można po prostu wykorzystać swoje wyniki:

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

i uniknąć jakieś dodatkowe pytania.

+1

Po uruchomieniu metody searchqueryset.load_all() wszystkie obiekty zostaną wstępnie załadowane z bazy danych tak wydajnie, jak to możliwe, zamiast pojedynczo. – melinath

+0

Z czymś w stylu "WYBIERZ * Z BŁĘDU, GDZIE ID (12, 1321251)" Czy to jest tak wydajne, aby otworzyć (być może) nowe gniazdo, pobrać dane z tego miejsca? – dzen

1

Od docs:

SearchQuerySet.load_all (self)

Skutecznie zapełnia obiektów w wynikach wyszukiwania. Bez użycia tej metody wyszukiwania DB są wykonywane dla poszczególnych obiektów, co powoduje wiele pojedynczych podróży do bazy danych. Jeśli użyta zostanie zmienna load_all, SearchQuerySet zgrupuje podobne obiekty w pojedynczą kwerendę, , uzyskując tylko tyle zapytań, ile jest zwracanych różnych typów obiektów: .

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

Dlatego po masz przefiltrowaną SQS, można zrobić load_all() na nim i tylko dostęp do obiektów bazy danych poprzez SearchResult.object. Na przykład.

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 
Powiązane problemy