browser-bug
browser-bug

Reputation: 2061

How to query by nearest neighbor on Cloud Firestore?

I'm quite new on the Firebase ecosystem and I'm wondering if there's a way to use a smart querying system using N-dimensional features vector.

We're trying to deploy a face-recognition application which, after computing its encoding (a vector of 128 features basically), tests it against the database (like cloud Firestore) to find the closest matching. From what I've understood the same task is usually achieved using PostgreSQL, apache sorl, etc. indexing the 128 fields and using a cube operator or a euclidean-distance like query with some quite reasonable timings. I think there's already something similar for geo-locations queries (Geofire).

Is there a way or some alternative options to perform this kind of task?

Upvotes: 0

Views: 1066

Answers (3)

theterminalguy
theterminalguy

Reputation: 1941

It's 2024, Google now supports this

You can perform a nearest neighbor query like so

import {
  Firestore,
  FieldValue,
  VectorQuery,
  VectorQuerySnapshot,
} from "@google-cloud/firestore";

// Requires single-field vector index
const vectorQuery: VectorQuery = coll.findNearest('embedding_field', FieldValue.vector([3.0, 1.0, 2.0]), {
  limit: 5,
  distanceMeasure: 'EUCLIDEAN'
});

const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
    

More info here https://firebase.google.com/docs/firestore/vector-search

Upvotes: 0

nuric
nuric

Reputation: 11225

Firestore does not have any in-built search yet unfortunately. But for your use case, you can try SemaDB Firebase which indexes your Firebase vector entries (facial features) and gives you a easy-to-use Cloud Function to search for:

const semadbSearch = functions.httpsCallable("ext-firestore-semadb-search-semadbSearch")
semadbSearch({ vector: <your query vector>}).then(/* ... */)

Disclaimer: I'm one of creators of SemaDB Firebase Extension.

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 599541

Firestore queries can only perform comparisons along a single axis. There is no built-in way for them to perform comparisons on multiple values, which is why GeoFire has to use geohash values to emulate multi-axis comparisons.

That is also your only option when it comes to other multi-value comparisons: package the values into a single value in a way that allows comparing those packed values in the way you need.

If your use-case also requires that you can compare two scalar values, and then get a range from within the resulting two-dimensional space, you can probably use a similar scheme of packing the two values into a string bit-by-bit. You might event be able to use GeoFire as a starting point, although you'll need to modify it to remove the fact that geofire's points are on a sphere.

If that doesn't work for you, I recommend looking at one of the solutions that more natively has support for your use-case.

Also see: The best way to query by location in firestore

Upvotes: 1

Related Questions