À l'aide de généré de façon aléatoire, des index et des requêtes simples, vous pouvez choisir au hasard des documents à partir d'une collection ou un groupe de collection dans le Cloud Firestore.
Cette réponse est divisé en 4 sections avec différentes options dans chaque section:
- Comment générer de façon aléatoire à l'index
- Comment interroger le hasard index
- Sélection de plusieurs documents aléatoires
- Le réensemencement pour les cours de l'aléatoire
Comment générer de façon aléatoire à l'index
La base de cette réponse, c'est la création d'un champ indexé que sur ordre croissant ou décroissant, les résultats dans le document en cours de façon aléatoire commandé. Il y a différentes façons pour créer cette, regardons donc 2, en commençant par le plus facilement disponible.
Auto-Id de la version
Si vous utilisez générés aléatoirement automatique des identifiants fournis dans nos bibliothèques client, vous pouvez utiliser ce même système, de sélectionner au hasard un document. Dans ce cas, le hasard a ordonné l'indice est l'id de document.
Plus tard dans notre section requête, la valeur aléatoire vous générez est une nouvelle auto-id (iOS, Android, Web) et le champ de recherche est l' __name__
champ, et le "faible valeur", évoqué plus tard est une chaîne vide. C'est de loin la méthode la plus simple pour générer de l'aléatoire, de l'index et fonctionne indépendamment de la langue et de la plateforme.
Par défaut, le nom du document (__name__
) est seulement indexés par ordre croissant, et vous ne pouvez pas renommer un document existant court de suppression et recréation. Si vous avez besoin de l'un de ces, vous pouvez toujours utiliser cette méthode et de l'enregistrer dans un auto-id comme un champ appelé random
plutôt que de surcharger le nom du document à cet effet.
Entier aléatoire version
Lorsque vous écrivez un document, d'abord générer un entier aléatoire dans un délimitée gamme et de le définir comme un champ appelé" random
. En fonction du nombre de documents que vous attendez, vous pouvez utiliser un autre délimitée gamme pour économiser de l'espace ou de réduire le risque de collisions (qui réduisent l'efficacité de cette technique).
Vous devez envisager les langues dont vous avez besoin, il y aura différentes considérations. Alors que Swift est facile, JavaScript notamment peut avoir un gotcha:
- Entier de 32 bits: parfait pour les petits (~10K peu probable d'avoir une collision) des ensembles de données
- 64-bit integer: Grands ensembles de données (remarque: JavaScript n'est pas nativement en charge, encore)
Cela va créer un index avec vos documents, classés de manière aléatoire. Plus tard dans notre section requête, la valeur aléatoire vous générez en aura un autre de ces valeurs, et la "faible valeur", évoqué plus tard sera -1.
Comment interroger le hasard index
Maintenant que vous avez un hasard index, vous aurez envie de l'interroger. Ci-dessous, nous examinons certaines de simples variantes pour sélectionner un 1 aléatoire document, ainsi que des options pour sélectionner plus de 1.
Pour toutes ces options, vous aurez envie de générer une nouvelle valeur aléatoire dans la même forme que les valeurs indexées vous avez créé lors de l'écriture du document, désigné par la variable random
ci-dessous. Nous allons utiliser cette valeur pour trouver un endroit aléatoire sur l'index.
Wrap-around
Maintenant que vous avez une valeur aléatoire, vous pouvez demander un document unique:
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
Vérifiez que cela a renvoyé un document. Si ce n'est pas, la requête de nouveau, mais l'utilisation de la "faible valeur" pour vos aléatoire de l'index. Par exemple, si vous n'avez Entiers Aléatoires alors lowValue
est 0
:
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: lowValue)
.order(by: "random")
.limit(to: 1)
Tant que vous avez un document unique, vous serez assuré de revenir au moins 1 document.
Bi-directionnel
Le wrap-around méthode est simple à mettre en œuvre et permet d'optimiser le stockage avec seulement un ordre croissant de l'indice de permis. Un inconvénient est la possibilité de valeurs injustement blindé. E. g si les 3 premiers documents (A,B,C) et hors de 10K avez des valeurs de l'indice d'Un:409496, B:436496, C:818992, alors A et C ont un peu moins de 1/10K chance d'être sélectionné, tandis que B est effectivement protégé par la proximité de l'Un et seulement environ un 1/160K chance.
Plutôt que d'interroger dans une seule direction et d'emballage autour si une valeur n'est pas trouvée, vous pouvez à la place choisir au hasard entre >=
et <=
, ce qui réduit la probabilité de injustement blindé valeurs par moitié, au prix de doubler le stockage des index.
Si une direction ne retourne pas de résultat, passez à l'autre direction:
queryRef = postsRef.whereField("random", isLessThanOrEqualTo: random)
.order(by: "random", descending: true)
.limit(to: 1)
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
Sélection de plusieurs documents aléatoires
Souvent, vous aurez envie de les sélectionner plus de 1 aléatoire document à la fois. Il y a 2 méthodes pour ajuster les techniques ci-dessus en fonction de ce compromis que vous voulez.
Rincer Et Répéter
Cette méthode est simple. Il suffit de répéter le processus, y compris la sélection d'un nouveau nombre entier aléatoire à chaque fois.
Cette méthode vous donnera des séquences aléatoires de documents sans se soucier de voir les mêmes modèles à plusieurs reprises.
En échange, il sera plus lente que la méthode suivante, car il nécessite un aller-retour pour le service pour chaque document.
Garder à venir
Dans cette approche, il suffit d'augmenter le nombre dans la limite du document désiré. C'est un peu plus complexe que vous pourriez retourner 0..limit
documents de l'appel. Vous aurez alors besoin d'obtenir les documents manquants de la même manière, mais avec la limite réduits à la différence. Si vous savez qu'il ya plus de documents au total que le numéro que vous demandez, vous pouvez optimiser en ignorant le cas limite de ne jamais avoir assez de recul documents sur le second appel (mais pas le premier).
L'inconvénient de cette solution est de séquences répétées. Alors que les documents sont ordonnés aléatoirement, si jamais vous en fin de chevauchement des plages, vous verrez le même modèle que vous avez vu avant. Il existe des moyens pour atténuer cette préoccupation discuté dans la section suivante sur le réensemencement.
Cette approche est plus rapide 'Rincer et Répéter" que vous serez en demandant à tous les documents dans le meilleur des cas, un seul appel ou un pire des cas 2 appels.
Le réensemencement pour les cours de l'aléatoire
Bien que cette méthode vous donne des documents au hasard si le document est statique de la probabilité de chaque document retournée sera statique ainsi. C'est un problème que certaines valeurs pourraient avoir injustement bas ou des probabilités élevées sur la base de valeurs aléatoires qu'ils ont obtenu. Dans de nombreux cas d'utilisation, c'est bien, mais dans certains cas, vous souhaiterez peut-être augmenter à long terme le caractère aléatoire de la plus uniforme de la chance de retourner tout document 1.
Notez que insérée documents sera à la fin tissé entre-deux, en train de changer progressivement les probabilités, comme la suppression des documents. Si l'insérer/supprimer des taux est trop petite compte tenu du nombre de documents, il existe quelques stratégies pour remédier à cela.
Multi-Aléatoire
Plutôt que de s'inquiéter de sortir le réensemencement, vous pouvez toujours créer plusieurs aléatoire index par le document, puis choisissez au hasard un de ces indices à chaque fois. Par exemple, le champ random
être une carte avec des sous-champs 1 à 3:
{'random': {'1': 32456, '2':3904515723, '3': 766958445}}
Maintenant, vous allez être d'interroger de façon aléatoire.1, aléatoire.2, aléatoire.3 au hasard, la création d'une plus grande propagation de l'aléatoire. Il s'agit essentiellement des métiers de stockage accrue pour économiser de l'augmentation de calcul (document écrit) d'avoir à effectuer un réamorçage.
Réamorçage sur l'écrit
Toute mise à jour d'un document de re-générer de la valeur aléatoire(s) de l' random
champ. Cela vous permettra de déplacer le document dans l'aléatoire de l'index.
Réamorçage sur le lit
Si les valeurs aléatoires générées ne sont pas uniformément réparties (ils sont aléatoires, donc c'est prévu), puis le même document peut être choisi un dispropriate montant de l'époque. Ceci est facilement compensé par la mise à jour de l'choisis au hasard document avec de nouvelles valeurs aléatoires après sa lecture.
Depuis les écritures sont plus cher et peut hotspot, vous pouvez choisir de mettre à jour uniquement sur la lecture d'un sous-ensemble de la période (e.g, if random(0,100) === 0) update;
).