Documents de requête Firestore avec un tableau similaire (Node.js/Admin SDK)
Imaginez que vous avez ce tableau
[10.3, 14, 12.4, 3.5]
et dans votre base de données, vous avez également deux documents avec ces tableaux :
First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]
Imaginez maintenant que vous avez +1000000 documents avec les deux mêmes tableaux (en alternance entre chacun)... Existe-t-il un moyen d'obtenir tous les documents qui ont des valeurs similaires à votre tableau actuel ?
Je veux dire, quelque chose comme ça :
...
.where("array", "isSimilar", yourArray)
.get()
Pour que j'obtienne tous les documents qui ont le tableau:
[10, 13.1, 0, -10]
Ou le seul moyen est de télécharger chaque document, quelque chose qui peut être très lent, puis de parcourir et de rechercher les plus similaires ? Je pense que cela peut être très intéressant lorsque l'on parle de "positions de points similaires", de "semaines au cours desquelles un utilisateur a perdu un poids similaire", ...
Merci.
Réponses
Pour le moment, Firestore ne prend pas en charge ce type de requête. Je vous suggère donc de mettre à jour votre structure pour inclure un champ String pour la comparaison de tableaux. Ainsi, chaque document ressemblerait à ceci :
{
array: [12, 11, 8, 9],
arrayStr: "12,11,8,9",
...
}
Vous pouvez obtenir cette structure simplement en appelant doc.array.join(",")
tous les documents existants et en enregistrant la valeur dans le document.
Ensuite, il sera possible de faire les comparaisons avec la requête firestore, comme ceci :
const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...
MISE À JOUR : Pour comparer par similarité au lieu d'égalité, une approche possible consiste à appliquer votre logique de "similarité" au arrayStr
champ lors de la création. Par exemple, si vous souhaitez que des différences inférieures à 0,5 soient tolérées, vous pouvez utiliser Math.round()
sur les éléments du tableau avant d'enregistrer en tant que chaîne. Ainsi:
const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"
Ensuite, vous interrogerez comme ceci :
const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.map(num => Math.round(num)).join(",")).get();
// Results would include arrays like [12.2, 10.7, 8.111, 9.0]
...
Bien sûr, vous pouvez varier l'argument passé à Math.round()
afin d'augmenter ou de réduire le niveau de tolérance pour les comparaisons