Dans ce numéro Est une demande de fonctionnalité permettant de commander avec une valeur de départ facultative permettant de recréer un ordre aléatoire.
Je dois être capable de paginer des résultats ordonnés au hasard. Comment cela pourrait-il être fait avec Elasticsearch 0.19.1?
Merci.
Vous pouvez trier à l'aide d'une fonction de hachage d'un champ unique (par exemple, id) et d'un sel aléatoire. En fonction du résultat réellement aléatoire, vous pouvez faire quelque chose d'aussi primitif que:
{
"query" : { "query_string" : {"query" : "*:*"} },
"sort" : {
"_script" : {
"script" : "(doc['_id'].value + salt).hashCode()",
"type" : "number",
"params" : {
"salt" : "some_random_string"
},
"order" : "asc"
}
}
}
ou quelque chose d'aussi sophistiqué que
{
"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"
}
}
}
Le deuxième exemple produira plus de résultats aléatoires mais sera un peu plus lent.
Pour que cette approche fonctionne, le champ _id
doit être enregistré. Sinon, la requête échouera avec NullPointerException
.
Cela devrait être considérablement plus rapide que les deux réponses ci-dessus et prend en charge le semis:
curl -XGET 'localhost:9200/_search' -d '{
"query": {
"function_score" : {
"query" : { "match_all": {} },
"random_score" : {}
}
}
}';
Voir: https://github.com/elasticsearch/elasticsearch/issues/1170
Bonne solution de imotov.
Voici quelque chose de beaucoup plus simple et vous n'avez pas besoin de compter dans une propriété de document:
{
"query" : { "query_string" : {"query" : "*:*"} },
"sort" : {
"_script" : {
"script" : "Math.random()",
"type" : "number",
"params" : {},
"order" : "asc"
}
}
}
si vous voulez définir une plage qui ressemblerait à quelque chose comme:
{
"query" : { "query_string" : {"query" : "*:*"} },
"sort" : {
"_script" : {
"script" : "Math.random() * (myMax - myMin) + myMin",
"type" : "number",
"params" : {},
"order" : "asc"
}
}
}
remplacer le max et le min par vos propres valeurs.
J'ai fini par résoudre le problème légèrement différemment de ce que suggérait imotov. Comme j'ai plusieurs clients, je ne voulais pas implémenter la logique entourant la chaîne de sel sur chacun d'entre eux.
J'ai déjà eu une randomized_key sur le modèle. Comme je n'avais pas besoin que l'ordre soit aléatoire pour chaque demande, j'ai donc programmé un travail pour mettre à jour la clé aléatoire chaque nuit, puis trié par champ dans Elasticssearch.
Eh bien, je cherchais à faire cela et toutes les approches ci-dessus semblaient un peu "trop compliquées" pour quelque chose qui devrait être relativement simple. Donc, je suis venu avec une alternative qui fonctionne parfaitement bien sans la nécessité de "devenir mental"
J'effectue d'abord une requête _count puis la combine avec "Démarrer" et Rand (0, $ count)
par exemple.
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);
Hypothèses pour l'exemple ci-dessus:
Mais vous n’avez PAS BESOIN de faire cela avec PHP, cette approche fonctionnerait avec n’importe quel exemple.