Documentos de consulta do Firestore com matriz semelhante (Node.js/Admin SDK)
Imagine que você tem essa matriz
[10.3, 14, 12.4, 3.5]
e no seu banco de dados você também tem dois documentos com esses arrays:
First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]
Agora imagine que você tem +1000000 documentos com os mesmos dois arrays (alternando entre cada um)... Existe alguma maneira de obter todos os documentos que possuem valores semelhantes ao seu array atual?
Quer dizer, algo assim:
...
.where("array", "isSimilar", yourArray)
.get()
Para que eu obtenha todos os documentos que possuem o array:
[10, 13.1, 0, -10]
Ou a única maneira é baixar todos os documentos, algo que pode ser muito lento, e depois iterar e pesquisar os mais semelhantes? Acho que isso pode ser muito interessante quando se fala em "posições de pontos semelhantes", "semanas em que um usuário perdeu peso semelhante", ...
Obrigado.
Respostas
No momento, o firestore não oferece suporte a esse tipo de consulta. Portanto, sugiro que você atualize sua estrutura para incluir um campo String para comparação de array. Portanto, cada documento ficaria assim:
{
array: [12, 11, 8, 9],
arrayStr: "12,11,8,9",
...
}
Você pode obter essa estrutura simplesmente chamando doc.array.join(",")
todos os documentos existentes e salvando o valor no documento.
Então, será possível fazer as comparações com a query firestore, assim:
const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...
ATUALIZAÇÃO: Para comparar por semelhança em vez de igualdade, uma abordagem possível é aplicar sua lógica de "semelhança" ao arrayStr
campo durante a criação. Por exemplo, se você deseja que diferenças menores que 0,5 sejam toleradas, você pode usar Math.round()
nos elementos da matriz antes de salvar como string. Igual a:
const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"
Então você vai consultar assim:
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]
...
Claro, você pode variar o argumento passado Math.round()
para aumentar ou diminuir o nível de tolerância para as comparações