2012-03-20 16 views

risposta

30

È possibile ordinare utilizzando una funzione di hash di un campo univoco (ad esempio id) e un salt casuale. A seconda di come realmente casuale i risultati dovrebbero essere, si può fare qualcosa di primitivo come:

{ 
    "query" : { "query_string" : {"query" : "*:*"} }, 
    "sort" : { 
    "_script" : { 
     "script" : "(doc['_id'].value + salt).hashCode()", 
     "type" : "number", 
     "params" : { 
      "salt" : "some_random_string" 
     }, 
     "order" : "asc" 
    } 
    } 
} 

o qualcosa di sofisticato come

{ 
    "query" : { "query_string" : {"query" : "*:*"} }, 
    "sort" : { 
    "_script" : { 
     "script" : "org.elasticsearch.common.Digest.md5Hex(doc['_id'].value + salt)", 
     "type" : "string", 
     "params" : { 
      "salt" : "some_random_string" 
     }, 
     "order" : "asc" 
    } 
    } 
} 

Il secondo esempio produrrà risultati più casuali, ma sarà un po 'più lento .

Per questo approccio al lavoro è necessario memorizzare il campo _id. In caso contrario, la query avrà esito negativo con NullPointerException.

+0

Vorrei memorizzare la stringa sul client allora? Ad esempio in un cookie? In modo che quando l'utente chiama per pagina 2, lo stesso ordine viene mantenuto? – Yeggeps

+0

La stringa salt deve essere generata e memorizzata sul layer che mantiene la sessione dell'utente. Può essere lo stesso posto in cui si memorizza la query dell'utente o il numero di pagina attualmente visualizzato. Può essere anche un cookie. – imotov

3

Ho finito per risolverlo leggermente diverso da quello che suggeriva imotov. Poiché ho più client, non ho voluto implementare la logica che circonda la stringa salt su ognuno di essi.

Ho già avuto un tasto randomized sul modello. Inoltre, non avevo bisogno che l'ordine fosse casuale per ogni richiesta, quindi ho fatto un lavoro programmato per aggiornare la chiave randomizzata ogni sera e poi ordinato per quel campo in Elasticssearch.

18

Buona soluzione da imotov.

Qui è qualcosa di molto più semplice e non è necessario fare affidamento in una proprietà del documento:

{ 
    "query" : { "query_string" : {"query" : "*:*"} }, 
    "sort" : { 
    "_script" : { 
     "script" : "Math.random()", 
     "type" : "number", 
     "params" : {}, 
     "order" : "asc" 
    } 
    } 
} 

se si desidera impostare una gamma che sarebbe qualcosa di simile:

{ 
    "query" : { "query_string" : {"query" : "*:*"} }, 
    "sort" : { 
    "_script" : { 
     "script" : "Math.random() * (myMax - myMin) + myMin", 
     "type" : "number", 
     "params" : {}, 
     "order" : "asc" 
    } 
    } 
} 

sostituendo il massimo e il minimo con i valori corretti.

+5

Questa è una buona soluzione generale. Tuttavia, la domanda iniziale chiedeva "semi facoltativi che permettessero di ricreare un ordine casuale". Ecco da dove viene tutta la complessità. – imotov

+0

Sì, hai completamente ragione. La mia soluzione è molto più adatta per il titolo "Ordine casuale e impaginazione Elasticsearch". Completamente insuficiente per i bisogni di Yeggeps. – DavidGOrtega

+3

risposta eccellente per l'ordinamento casuale di base, grazie – Eva

50

Questo dovrebbe essere notevolmente più veloce di entrambe le risposte di cui sopra e supporta semina:

curl -XGET 'localhost:9200/_search' -d '{ 
    "query": { 
    "function_score" : { 
     "query" : { "match_all": {} }, 
     "random_score" : {} 
    } 
    } 
}'; 

See: https://github.com/elasticsearch/elasticsearch/issues/1170

+1

Grazie per il vostro aiuto. Penso che la risposta renderebbe più chiaro che random_score supporta il seeding se aggiorni la query di esempio. –

+0

Non funziona se si utilizzano i filtri. –

0

Bene, stavo guardando fare questo e tutti gli approcci sopra sembrava un po ' "troppo complicato "per qualcosa che dovrebbe essere relativamente semplice. Così mi è venuta con un'alternativa che funziona perfettamente, senza la necessità di "andare mentale"

effettuo una query _count prima poi combinarlo con "Start" e rand (0, $ count)

esempio

JSONArray = array of json to send to ElasticSearch 
$total_results = $ElasticSearchClient->count(JSONArray) 
$start = rand(0, $total_results) 
JSONArray['body']['from'] = $start; 
$ElasticSearchClient->search(JSONArray); 

Ipotesi per l'esempio precedente:

  • Si sta eseguendo PHP
  • Sei anche utilizzando il client PHP

Ma non avete bisogno di fare questo con PHP, l'approccio funzionerebbe con qualsiasi esempio.

Problemi correlati