2010-01-29 13 views
10

¿Es posible combinar una búsqueda Django Haystack con operaciones de filtro QuerySet "integradas", específicamente filtrando con instancias Q() y tipos de búsqueda no compatibles con SearchQuerySet? En cualquier orden:¿Filtrar los resultados de Django Haystack como QuerySet?

haystack-searched -> queryset-filtered 

o

queryset-filtered -> haystack-searched 

Navegar por la documentación de Django Haystack no dará instrucciones de cómo hacer esto.

Respuesta

10

Se puede filtrar el conjunto de consultas sobre la base de los resultados de una búsqueda Haystack, utilizando PK de los objetos:

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

seguro de cómo las escalas, pero para conjuntos de resultados pequeños (unos pocos cientos, en mi caso) , esto funciona bien

+6

con esto, sus resultados serán ordenados por ID, y perderá la pertinencia. – dzen

+0

@dzen ¿cuál es la mejor manera de hacer esto mientras se conserva el rango de relevancia, entonces? –

+5

Esto no escala. Supongo que la consulta es demasiado larga: con un par de miles de ID habrá 0 resultados. –

0

Si desea mantenerse al día con la pertinencia, usted tiene que tener acceso al objeto de la base de datos a través de "objeto":

ejemplo en su plantilla:

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

pero esto es realmente malo ya haystack hará una solicitud adicional como "SELECT * FROM blah WHERE id = 42" en cada resultado.

Parece que está tratando de obtener esos objetos de su base de datos porque no puso algunos campos adicionales en su índice, ¿no es así? Si se agrega el título y el autor en su SearchIndex, a continuación, puedes utilizar sus resultados:

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

y evitar algunas consultas adicionales.

+1

Si ejecuta searchqueryset.load_all(), todos los objetos se precargarán de la base de datos de la forma más eficiente posible, en lugar de uno a la vez. – melinath

+0

Con algo así como "SELECT * FROM bla WHERE id in (12, 132,1251)" Entonces, ¿eso es eficiente, abrir (tal vez) un nuevo socket, buscar datos desde allí? – dzen

1

A partir de los documentos:

SearchQuerySet.load_all (auto)

puebla de manera eficiente los objetos en los resultados de búsqueda. Sin usar este método, las búsquedas de base de datos se realizan por objeto, lo que da como resultado muchos viajes individuales a la base de datos. Si se usa load_all, el SearchQuerySet agrupará objetos similares en una única consulta, , dando como resultado solo tantas consultas como tipos de objetos diferentes devueltos.

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

Por lo tanto, después de tener un SQS filtrados, se puede hacer un load_all() sobre ella y simplemente acceder a los objetos de bases de datos a través de SearchResult.object. P.ej.

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 
Cuestiones relacionadas