Reputation: 2061
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
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
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
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