Domanda

Sto costruendo un piccolo motore di ricerca utilizzando Django Haystack + Elasticsearch + Django REST Framework e sto cercando di riprodurre il comportamento di un Django QuerySet'S distinct metodo.

Il mio indice è simile a questo:

class ItemIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    item_id = indexes.IntegerField(faceted=True)

    def prepare_item_id(self, obj):
        return obj.item_id

Quello che mi piacerebbe poter fare è il seguente:

sqs = SearchQuerySet().filter(content=my_search_query).distinct('item_id')

Tuttavia, Haystack's SearchQuerySet non ha un distinct metodo, quindi sono un po' perso.Ho provato ad sfaccettare il campo e quindi a interrogare Django utilizzando l'elenco restituito di item_id's, ma questo perde le prestazioni di Elasticsearch e rende anche impossibile utilizzare le funzionalità di ordinamento di Elasticsearch.

qualche idea?

MODIFICARE:

Dati di esempio:

Dati di esempio:

Item Model
==========

id  title
1   'Item 1'
2   'Item 2'
3   'Item 3'


VendorItem Model << the table in question
================

id  item_id  vendor_id  lat   lon
1   1        1          38    -122
2   2        1          38.2  -121.8
3   3        2          37.9  -121.9
4   1        2          ...   ...
5   2        2          ...   ...
6   2        3          ...   ...

Come puoi vedere, ci sono più VendorItem per lo stesso articolo, tuttavia durante la ricerca desidero recuperare al massimo un risultato per ciascun articolo.Pertanto ho bisogno del item_id la colonna deve essere univoca/distinta.

Ho provato a sfaccettare il file item_id colonna e quindi eseguendo la seguente query:

facets = SearchQuerySet().filter(content=query).facet('item_id')
counts = sqs.facet_counts()

# ids will look like: [345, 892, 123, 34,...]
ids = [i[0] for i in counts['fields']['item_id']]

items = VendorItem.objects.filter(vendor__lat__gte=latMin,
    vendor__lon__gte=lonMin, vendor__lat__lte=latMax,
    vendor__lon__lte=lonMax, item_id__in=ids).distinct(
        'item').select_related('vendor', 'item')

Il problema principale qui è che i risultati sono limitati a 100 elementi e non possono essere ordinati nel pagliaio.

È stato utile?

Soluzione

Penso che il miglior consiglio che posso darti è di smettere di usare Haystack.

Il backend predefinito di Haystack (elasticsearch_backend.py) è scritto principalmente pensando a Solr.Ci sono molti fastidi che trovo in Haystack, ma il più grande è che racchiude tutte le query in qualcosa chiamato query_string.Utilizzando la stringa di query, possono utilizzare la sintassi lucene, ma ciò significa anche perdere l'intero DSL elasticsearch.La sintassi lucene presenta alcuni vantaggi, soprattutto se è ciò a cui sei abituato, ma è molto limitante dal punto di vista dell'elasticsearch.

Inoltre, penso che tu stia applicando un concetto RDBMS a un motore di ricerca.Ciò non vuol dire che non dovresti ottenere i risultati di cui hai bisogno, ma l'approccio è spesso diverso.

Il modo in cui potresti interrogare e recuperare questi dati potrebbe essere diverso se non usi haystack perché haystack crea indici in un modo più appropriato per solr che per elasticsearch.

Ad esempio, nella creazione di un nuovo indice, Haystack assegnerà un "tipo" chiamato "modelresult" a tutti i modelli che verranno inseriti in un indice.

Quindi, supponiamo che tu abbia alcune entità chiamate Items e alcune altre entità chiamate selleritems.

Potrebbe essere appropriato averli entrambi nello stesso indice ma con VendorItems come tipo di VendorItems e gli articoli con un tipo di Items.

Durante l'esecuzione di una query, eseguiresti quindi una query in base all'endpoint resto, quindi qualcosa di simile localhost:9200/index/type (query).Il modo in cui Haystack ottiene questo risultato è attraverso il modulo dei tipi di contenuto Django.Di conseguenza, esiste un campo chiamato "django_ct" che mette in pagliaio le query e si allega a qualsiasi query che potresti fare quando stai cercando solo elementi unici.

Per illustrare quanto sopra:

Questo endpoint esegue la ricerca in tutti gli indici

`localhost:9200/`

Questo endpoint esegue la ricerca in tutti i tipi in un indice:

`localhost:9200/yourindex/`

Questo endpoint cerca in un tipo all'interno di un indice:

`localhost:9200/yourindex/yourtype/`

e questo endpoint esegue la ricerca in due tipi specificati all'interno di un indice:

`localhost:9200/yourindex/yourtype,yourothertype/`

Tornando al pagliaio, però, puoi ottenere valori univoci aggiungendo un django_ct alla tua query, ma probabilmente non è quello che desideri.

Ciò che vuoi veramente fare è una sfaccettatura e probabilmente vorrai usare le sfaccettature dei termini.Questo potrebbe essere un problema nel pagliaio perché A.) analizza tutto il testo e B.) applica store=True a tutti i campi (in realtà non qualcosa che vuoi fare in elasticsearch, ma qualcosa che vuoi fare spesso in solr).

È possibile ordinare i risultati delle sfaccettature in elasticsearch (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html#_ordering)

Non intendo che questo sia uno schianto nel pagliaio.Penso che faccia molte cose bene concettualmente.È particolarmente utile se tutto ciò che devi fare è indicizzare un singolo modello (come ad esempio un blog) e far sì che restituisca rapidamente risultati.

Detto questo ne consiglio vivamente l'utilizzo elasticutils.Alcuni concetti di Haystack sono simili, ma utilizza la ricerca dsl anziché query_string (ma puoi comunque utilizzare query_string se lo desideri).

Attenzione però, non penso che tu possa ordinare le sfaccettature usando elasticutils per impostazione predefinita, ma puoi semplicemente passare un dizionario Python delle sfaccettature che desideri facet_raw metodo (qualcosa che non credo si possa fare nel pagliaio).

La tua ultima opzione è creare il tuo backend haystack, ereditare dal backend esistente e aggiungere semplicemente alcune funzionalità al metodo .facet() per consentire l'ordine in base al dsl sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top