Dokumenty zapytań Firestore z podobną tablicą (Node.js / Admin SDK)
Wyobraź sobie, że masz tę tablicę
[10.3, 14, 12.4, 3.5]
aw swojej bazie danych masz również dwa dokumenty z tymi tablicami:
First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]
Teraz wyobraź sobie, że masz +1000000 dokumentów z tymi samymi dwiema tablicami (naprzemiennie między każdą z nich) ... Czy istnieje sposób, aby uzyskać wszystkie dokumenty, które mają podobne wartości jak Twoja aktualna tablica?
Mam na myśli coś takiego:
...
.where("array", "isSimilar", yourArray)
.get()
Tak więc otrzymuję wszystkie dokumenty, które mają tablicę:
[10, 13.1, 0, -10]
A może jedynym sposobem jest pobranie każdego dokumentu, coś, co może być naprawdę powolne, a następnie powtórzenie i wyszukanie najbardziej podobnego? Myślę, że może to być naprawdę interesujące, gdy mówimy o „podobnych pozycjach punktów”, „tygodniach, w których użytkownik stracił podobną wagę”, ...
Dzięki.
Odpowiedzi
W tej chwili Firestore nie obsługuje tego rodzaju zapytań. Dlatego proponuję zaktualizować strukturę, aby zawierała pole typu String do porównania tablic. Więc każdy dokument wyglądałby tak:
{
array: [12, 11, 8, 9],
arrayStr: "12,11,8,9",
...
}
Możesz osiągnąć tę strukturę, po prostu wywołując doc.array.join(",")
wszystkie istniejące dokumenty i zapisując wartość w dokumencie.
Następnie będzie można dokonać porównań z zapytaniem Firestore, na przykład:
const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...
AKTUALIZACJA: Aby porównać podobieństwo zamiast równości, możliwym podejściem jest zastosowanie logiki „podobieństwa” do arrayStr
pola podczas tworzenia. Na przykład, jeśli chcesz, aby różnice mniejsze niż 0,5 były tolerowane, możesz użyć Math.round()
na elementach tablicy przed zapisaniem jako ciąg. Tak jak to:
const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"
Następnie zapytasz w ten sposób:
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]
...
Oczywiście można zmienić przekazany argument Math.round()
, aby zwiększyć lub zmniejszyć poziom tolerancji porównań