Документы запросов Firestore с аналогичным массивом (Node.js / Admin SDK)
Представьте, что у вас есть этот массив
[10.3, 14, 12.4, 3.5]
и в вашей БД у вас также есть два документа с этими массивами:
First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]
Теперь представьте, что у вас есть +1000000 документов с одинаковыми двумя массивами (чередующимися между собой) ... Есть ли способ получить все документы, которые имеют аналогичные значения, как ваш текущий массив?
Я имею в виду, что-то вроде этого:
...
.where("array", "isSimilar", yourArray)
.get()
Чтобы получить все документы, в которых есть массив:
[10, 13.1, 0, -10]
Или единственный способ - загрузить каждый документ, что может быть очень медленным, а затем выполнить итерацию и найти наиболее похожие? Я думаю, это может быть действительно интересно, когда мы говорим о «схожих позициях», «неделях, в течение которых пользователь похудел примерно так же», ...
Спасибо.
Ответы
На данный момент firestore не поддерживает такие запросы. Поэтому я предлагаю вам обновить свою структуру, включив в нее поле String для сравнения массивов. Итак, каждый документ будет выглядеть так:
{
array: [12, 11, 8, 9],
arrayStr: "12,11,8,9",
...
}
Вы можете получить эту структуру, просто вызвав doc.array.join(",")
все существующие документы и сохранив значение в документе.
Затем можно будет провести сравнение с запросом firestore, например:
const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...
ОБНОВЛЕНИЕ: для сравнения по сходству, а не по равенству, возможный подход - применить логику «подобия» к arrayStr
полю во время создания. Например, если вы хотите, чтобы допускались различия менее 0,5, вы можете использовать Math.round()
их для элементов массива перед сохранением в виде строки. Вот так:
const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"
Тогда вы будете запрашивать вот так:
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]
...
Конечно, вы можете изменить переданный аргумент Math.round()
, чтобы увеличить или уменьшить уровень допуска для сравнений.