Firestore-Abfragedokumente mit ähnlichem Array (Node.js/Admin SDK)

Aug 16 2020

Stellen Sie sich vor, Sie haben dieses Array

[10.3, 14, 12.4, 3.5]

und in Ihrer DB haben Sie auch zwei Dokumente mit diesen Arrays:

First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]

Stellen Sie sich nun vor, Sie haben +1000000 Dokumente mit denselben zwei Arrays (jeweils abwechselnd) ... Gibt es eine Möglichkeit, alle Dokumente zu erhalten, die ähnliche Werte wie Ihr aktuelles Array haben?

Ich meine so etwas:

   ...
   .where("array", "isSimilar", yourArray)
   .get()

Damit ich alle Dokumente bekomme, die das Array haben:

[10, 13.1, 0, -10]

Oder besteht die einzige Möglichkeit darin, jedes einzelne Dokument herunterzuladen, was sehr langsam sein kann, und dann zu iterieren und nach dem ähnlichsten zu suchen? Ich denke, das kann sehr interessant sein, wenn es um "ähnliche Punktepositionen", "Wochen, in denen ein Benutzer ähnliches Gewicht verloren hat", ...

Vielen Dank.

Antworten

3 JayCodist Aug 16 2020 at 09:20

Im Moment unterstützt Firestore diese Art von Abfragen nicht. Daher schlage ich vor, dass Sie Ihre Struktur aktualisieren, um ein String-Feld für den Array-Vergleich einzuschließen. Jedes Dokument würde also so aussehen:

{
   array: [12, 11, 8, 9],
   arrayStr: "12,11,8,9",
   ...
}

Sie erreichen diese Struktur einfach, indem Sie doc.array.join(",")alle vorhandenen Dokumente aufrufen und den Wert im Dokument speichern.

Dann ist es möglich, die Vergleiche mit der Firestore-Abfrage wie folgt durchzuführen:

const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...

UPDATE: Um nach Ähnlichkeit statt nach Gleichheit zu vergleichen, besteht ein möglicher Ansatz darin, Ihre "Ähnlichkeitslogik" arrayStrwährend der Erstellung auf das Feld anzuwenden. Wenn Sie beispielsweise möchten, dass Unterschiede von weniger als 0,5 toleriert werden, können Sie Math.round()die Array-Elemente verwenden, bevor Sie sie als Zeichenfolge speichern. So:

const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"

Dann fragen Sie so ab:

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]
...

Natürlich könnten Sie das übergebene Argument variieren Math.round(), um die Toleranz für die Vergleiche zu erhöhen oder zu verringern