Commander un ensemble de résultats au hasard dans Mongo
J'ai découvert récemment que Mongo a pas de SQL équivalent à "ORDER BY RAND()" dans la syntaxe de commande (https://jira.mongodb.org/browse/SERVER-533)
J'ai vu la recommandation de la http://cookbook.mongodb.org/patterns/random-attribute/ et franchement, l'ajout d'un attribut aléatoire d'un document se sent comme un hack. Cela ne marchera pas, parce que cela met une limite implicite à toute requête que je veux rendre aléatoire.
L'autre largement donnée suggestion est de choisir un hasard de l'indice de décalage. En raison de l'ordre que mes documents ont été insérés dans, qui aboutira dans l'un des champs de type chaîne étant classés par ordre alphabétique, qui ne se sentent pas très aléatoire à un utilisateur de mon site.
J'ai quelques idées sur comment je pourrais résoudre ce via le code, mais je sens que je vais manquer un plus évidente et la solution native. Quelqu'un aurait-il une pensée ou une idée sur comment résoudre ce problème de manière plus élégante?
source d'informationauteur Andy Baird
Vous devez vous connecter pour publier un commentaire.
Je suis d'accord: la chose la plus facile à faire est d'installer une valeur aléatoire dans vos documents. Il n'a pas besoin d'être extrêmement large gamme de valeurs, que ce soit -- le nombre que vous choisissez dépend du résultat attendu de la taille de vos requêtes (de 1 000 - 1 000 000 d'entiers distincts devrait être suffisant pour la plupart des cas).
Lorsque vous exécutez votre requête, ne vous inquiétez pas sur le champ aléatoire -- au lieu de cela, de l'index et de l'utiliser pour le tri. Depuis il n'y a pas de correspondance entre le nombre aléatoire et le document, vous devriez obtenir assez aléatoire de résultats. Notez que les collisions seront probablement entraîner dans les documents retournés dans l'ordre naturel.
Tout ce est certainement un hack, vous avez une très facile d'échappatoire: donnée MongoDB du schéma, vous pouvez simplement arrêter, y compris le champ aléatoire une fois qu'il est aléatoire de tri dans le serveur. Si la taille est un problème, vous pouvez exécuter un travail par lots pour supprimer le champ à partir de documents existants. Il ne devrait pas être un changement important dans votre code client si vous avez la conception de la lire attentivement.
Une alternative serait de penser à long et dur sur le nombre de résultats, qui seront randomisés et retournée pour une requête donnée. Il peut ne pas être trop cher pour le faire simplement traînant dans le code client (c'est à dire, si l'on ne considère que les plus récentes de 10 000 postes).
Ce que vous voulez ne peut pas être fait sans choisir l'une des deux solutions que vous mentionnez. Sélection d'un décalage aléatoire est une idée horrible si votre collection devient plus grande que quelques milliers de documents. La raison pour cela est que le saut(n) opération prend O(n) fois. En d'autres termes, plus votre décalage aléatoire le long de la requête.
L'ajout d'un essai randomisé champ du document est, à mon avis, le moins que l'hacky la solution étant donné le jeu de fonctionnalités de MongoDB. Il offre une stabilité de requête et vous donne quelques mot à dire sur la façon dont la collecte est aléatoire (et permet de générer une nouvelle valeur aléatoire après chaque requête par le biais d'un findAndModify par exemple). Aussi je ne comprends pas comment ce serait imposer une limite implicite sur vos requêtes que faire usage de la randomisation.
Vous pouvez donner à ceci un essai - c'est rapide, fonctionne avec de nombreux documents et ne nécessite pas de remplissage
rand
champ au début, qui finira par remplir lui-même:Pourquoi? Si vous avez 7.000 documents et que vous choisissez trois aléatoire des décalages de 0 à 6999 le choix de documents sera aléatoire, même si la collection elle-même est triée par ordre alphabétique.
On pouvait insérer un champ id ($id champ ne fonctionnera pas parce que ses pas un nombre réel) utiliser le module math pour obtenir un aléatoire sauter. Si vous avez 10 000 enregistrements et que vous vouliez 10 résultats vous pouvez choisir un module d'élasticité compris entre 1 et 1000 au hasard comme 253, puis demande où mod(id,253)=0 et c'est assez rapide si l'id est indexé. Au hasard, puis trier client à côté de ceux de 10 résultats. Assurez-vous qu'ils sont régulièrement espacés au lieu de vraiment aléatoire, mais proche de ce qui est souhaité.
Les deux options semble que non parfait hacks pour moi, aléatoire déposé et aura toujours la même valeur et passer sera de retour même les enregistrements pour un même nombre.
Pourquoi n'utilisez-vous pas un hasard champ à trier puis passez au hasard, je l'avoue, c'est aussi un hack, mais dans mon expérience, donne un meilleur sens de l'aléatoire.