Il est crucial que mon application puisse sélectionner aléatoirement plusieurs documents dans une collection dans Firebase.
Comme il n'y a pas de fonction native intégrée dans Firebase (pour autant que je sache) pour implémenter une requête pour ce faire, ma première pensée a été d'utiliser un curseur de requête pour choisir un index de début et de fin aléatoire, en supposant que j'avais une collection de nombres Le nombre de documents dans .
Cette approche fonctionne, mais seulement de manière limitée, car chaque document sera servi séquentiellement avec son voisin à chaque fois ; cependant, je peux réaliser une randomisation si je suis capable de sélectionner un document par son index dans sa requête de documentation de collection parent, mais le problème est que je ne trouve aucune documentation décrivant comment procéder, ni même s'il est possible de le faire.
C'est ce que je veux faire, considérez l'architecture Firestore suivante :
root/ posts/ docA docB docC docD
Puis côté client (je suis dans un environnement Swift) je souhaite écrire une requête qui fait ceci :
db.collection("posts")[0, 1, 3] // would return: docA, docB, docD
Puis-je faire quelque chose de similaire ? Alternativement, existe-t-il un autre moyen de sélectionner des documents aléatoires de la même manière ?
S'il vous plaît, aidez-moi.
Je publie ceci pour aider toute personne rencontrant ce problème à l'avenir.
Si vous utilisez l'identification automatique, vous pouvez générer une nouvelle identification automatique et interroger l'identification automatique la plus proche, comme dans Réponse de Dan McGrath.
J'ai récemment créé une API de citations aléatoires qui devait obtenir des citations aléatoires à partir d'une collection Firestore.
Voici comment j'ai résolu ce problème :
La clé de la requête est la suivante :
Si aucun document n'est trouvé, rappelez avec l'opération inverse.
J'espère que cela vous aidera !
À l'aide d'un index généré aléatoirement et d'une simple requête, vous pouvez sélectionner aléatoirement des documents dans une collection ou un groupe de collections dans Cloud Firestore.
Cette réponse est divisée en 4 parties, chacune avec des options différentes :
Comment générer un index aléatoire
La base de cette réponse est de créer un champ d'index qui, lorsqu'il est trié par ordre croissant ou décroissant, entraînera le tri aléatoire de tous les documents. Il existe un certain nombre de façons différentes de créer cela, alors examinons-en 2, en commençant par la méthode la plus accessible.
Identifier automatiquement la version
Si vous utilisez les identifiants automatiques générés aléatoirement fournis dans notre bibliothèque client, vous pouvez utiliser le même système pour sélectionner des documents de manière aléatoire. Dans ce cas, l'index ordonné aléatoirement est l'identifiant du document.
Plus tard dans notre section de requête, la valeur aléatoire que vous avez générée est un nouvel identifiant automatique (iOS, Android, Web), le champ que vous interrogez est le champ
__name__
, et la valeur faible « mentionné plus tard » est une chaîne vide. C'est de loin le moyen le plus simple de générer un index aléatoire et fonctionnera quelles que soient la langue et la plate-forme.Par défaut, les noms de documents (
au lieu de surcharger le nom du document à cet effet.__name__
) 仅按升序索引,并且除了删除和重新创建之外,您也无法重命名现有文档。如果您需要其中任何一个,您仍然可以使用此方法,只需将自动 ID 存储为名为random
) sont indexés uniquement par ordre croissant, et vous ne pouvez pas non plus renommer les documents existants sauf en les supprimant et en les recréant. Si vous avez besoin de l'un ou l'autre de ces éléments, vous pouvez toujours utiliser cette méthode, stockez simplement l'ID automatique sous la forme d'un champ réel nommérandom
Lorsque vous rédigez un document, générez d'abord un entier aléatoire dans une plage délimitée et définissez-le sur un champ nomméCela créera un index avec des documents triés de manière aléatoire. Plus loin dans notre section de requête, la valeur aléatoire que vous générez sera une autre de ces valeurs, et la « valeur faible » mentionnée plus tard sera -1.
Comment interroger un index aléatoire
Maintenant que vous disposez d'un index aléatoire, vous devrez l'interroger. Ci-dessous, nous examinons quelques variantes simples qui sélectionnent 1 document aléatoire, ainsi que les options de sélection de plusieurs 1 documents.
Pour toutes ces options, vous devez générer une nouvelle valeur aléatoire sous la même forme que la valeur d'index que vous avez créée lors de la rédaction du document, représentée par la variable
random
ci-dessous. Nous utiliserons cette valeur pour trouver des points aléatoires sur l'index.Enveloppant
Maintenant que vous disposez de valeurs aléatoires, vous pouvez interroger des documents individuels :
Vérifiez si le document a été retourné. Sinon, interrogez à nouveau, mais avec la "valeur faible" de l'index aléatoire. Par exemple, si vous faites des entiers aléatoires, alors
lowValue
为0
:Tant que vous disposez d'un document, vous êtes assuré de retourner au moins 1 document.
Les deux sens
La méthode wrap est simple à mettre en œuvre et permet d'optimiser le stockage avec uniquement l'indexation ascendante activée. Un inconvénient est que les valeurs peuvent être injustement protégées. Par exemple, si les 3 premiers documents de 10K (A, B, C) ont des valeurs d'index aléatoires A:409496, B:436496, C:818992, alors la chance que A et C soient sélectionnés est inférieure à 1/10K. , tandis que B sera sélectionné car A est efficacement protégé de la proximité et n'a qu'une chance d'environ 1/160K.
Vous pouvez choisir au hasard entre
>=
和Au lieu d'une requête unidirectionnelle et d'un retour en arrière lorsqu'une valeur n'est pas trouvée, cela réduit de moitié la probabilité de masquer injustement la valeur au prix de doubler le stockage de l'index.
Si aucun résultat n'est renvoyé dans un sens, passez dans l'autre sens :
Sélectionnez plusieurs documents aléatoires
Habituellement, vous devez sélectionner plusieurs documents aléatoires à la fois. Il existe deux manières différentes d'adapter les techniques ci-dessus en fonction des compromis souhaités.
Rincez et répétez
Cette méthode est très simple. Répétez simplement le processus, notamment en choisissant à chaque fois un nouvel entier aléatoire.
Cette méthode vous donnera une séquence aléatoire de documents sans avoir à vous soucier de voir le même motif à plusieurs reprises.
Le compromis est qu'elle sera plus lente que la méthode suivante car elle nécessite un aller-retour séparé pour servir chaque document.
Continuez ainsi
Dans cette méthode, augmentez simplement le nombre limite de documents requis. C'est un peu compliqué car vous pourriez renvoyer un document
0..limit
lors de l'appel. Ensuite, vous devez obtenir le document manquant de la même manière, mais avec les limitations réduites aux seules différences. Si vous savez que le nombre total de documents est supérieur à ce que vous demandez, vous pouvez optimiser en ignorant le cas limite où suffisamment de documents ne sont jamais récupérés lors du deuxième appel (mais pas du premier).Le compromis avec cette solution est la séquence répétitive. Bien que les documents soient triés de manière aléatoire, si vous vous retrouvez avec des plages qui se chevauchent, vous verrez le même modèle que précédemment. Il existe des moyens d'atténuer ce problème, dont nous discuterons dans la section suivante sur le réensemencement.
Cette méthode est plus rapide que « rincer et répéter » car vous demanderez tous les documents en un seul appel dans le meilleur des cas ou deux appels dans le pire des cas.
Reseed pour un caractère aléatoire cohérent
Bien que cette méthode vous donnera des documents de manière aléatoire si l'ensemble de documents est statique, la probabilité de renvoyer chaque document sera également statique. C'est un problème car certaines valeurs peuvent avoir des probabilités injustement faibles ou élevées en fonction de la valeur aléatoire initiale à partir de laquelle elles ont été obtenues. Dans de nombreux cas d'utilisation, cela convient, mais dans certains cas, vous souhaiterez peut-être augmenter le caractère aléatoire à long terme afin qu'il y ait une chance plus égale qu'un document soit renvoyé.
Notez que les documents insérés finissent par s'entrelacer au milieu, modifiant progressivement les probabilités, et il en va de même pour les documents supprimés. Si le taux d'insertion/suppression est trop faible pour un nombre donné de documents, il existe quelques stratégies pour résoudre ce problème.
Plusieurs aléatoires
Vous n'avez pas à vous soucier du réamorçage, vous pouvez toujours créer plusieurs index aléatoires par document et en sélectionner un au hasard à chaque fois. Par exemple, soit le champ
random
une carte contenant les sous-champs 1 à 3 :Vous allez maintenant interroger aléatoirement random.1, random.2, random.3, créant ainsi une plus grande distribution de caractère aléatoire. Cela utilise essentiellement un espace de stockage accru pour économiser le calcul accru (écriture de documents) du réamorçage.
Réensemencer en écrivant
Chaque fois que le document est mis à jour, une valeur aléatoire pour le champ
random
sera régénérée. Cela déplacera les documents dans un index aléatoire.Réensemencement en lecture
Si les valeurs aléatoires générées ne sont pas uniformément réparties (elles sont aléatoires, c'est donc normal), le même document peut être sélectionné à des moments inappropriés. Ce problème peut être facilement résolu en mettant à jour un document sélectionné au hasard avec de nouvelles valeurs aléatoires après l'avoir lu.
Étant donné que les écritures sont plus coûteuses et peuvent devenir des points chauds, vous pouvez choisir de mettre à jour uniquement à un sous-ensemble du temps de lecture (par exemple
if random(0,100) === 0) update;
).