-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MEVD] Filter-only search API (without vector similarity) #10295
Comments
We should first do a cross-database comparison to validate that most/all databases have this capability (I'd be very surprised if that's not the case). Beyond that, I'm tentatively proposing the name QueryAsync() for the new API. The verb Query (as opposed to Search, SimilaritySearch...) seems to connect quite well with the idea of traditional, keyword-only SQL filtering (e.g. "SQL queries"). This is incidentally also the naming distinction that Milvus makes (Search vs. Query). |
I've done some quick research around the capabilities of the Vector DBs (for relational and NoSQL I assumed it simply has to be supported) Short summary:
So I am going to start with an API that takes mandatory filter and |
Thanks for this Adam!
Great, that validates the need to expose this in the abstraction.
When you say sorting/ordering, do you mean that databases simply allow picking a metadata property to sort by? Or is there more advanced support with expressions or something? If it's the former, then we'd just have a property selector (just like we do for selecting the vector property). In any case, if Pinecone is the only one to not support this, it sounds like it definitely makes sense having it on the abstraction. I'm guessing it should be optional? If not specified, do databases just return random/undetermined ordering, or error?
Yep, see #10193 for the same thing on the regular search API; whatever we decide to do should be done on both these search types (and also on the hybrid search API) for consistency. I'm happy for you to take over #10193 if you want - the main thing is making sure everyone agrees about the right thing here (/cc @westey-m @dmytrostruk).
That's an interesting one, and actually connects to general database questions about pagination efficiency; implementing pagination ("skipping") by giving an ID/key is actually typically the more efficient way to do things (see these docs, this post). I'm curious why they chose to actually expose a Skip property on the API, given that you should already be able to simply do the same thing in the regular filter (i.e. Maybe open an issue for us to look at this later, and throw for now if Skip is provided? |
Update: The Vector property for Pincone There is a For now I am using |
I don't know yet. I am just afraid that if we don't expose |
Yep, that is how SQL works as well - you can specify LIMIT/OFFSET without ORDER BY, and get non-deterministic results. FWIW LIMIT can make sense without ORDER BY ("give me any 10 elements") but OFFSET not so much. EF warns for (most) such queries. I don't think we should worry too much about this... Since almost all databases seem to support OrderBy, it seems obvious we should support that - if the user doesn't set it while using limit/offset, at the end of the day it's their problem... |
All the connectors except of Pinceone, do support ordering the results. But unlike other connectors, Redis and Qdrant allow to sort only by a single property. For now, I've implemented a very simple approach where the user might provide a single public sealed class QueryOptions<TRecord>
{
public Expression<Func<TRecord, object?>>? OrderBy { get; init; }
public bool SortAscending { get; init; }
}
await fixture.Collection.QueryAsync(new()
{
Filter = filter,
Top = top,
OrderBy = r => r.Int // selecting a single property
}).ToListAsync()); An alternative would be to expose a func expression that takes a public sealed class QueryOptions<TRecord>
{
public Expression<Func<IQueryable<TRecord>, IOrderedQueryable<TRecord>>>? OrderByExpression { get; init; }
}
await fixture.Collection.QueryAsync(new()
{
Filter = filter,
Top = top,
OrderByExpression = input => input.OrderBy(x => x.Int).ThenByDescending(x => x.String)
}).ToListAsync()); Links to docs:
@roji let's sync and chat about it |
@adamsitnik great work, thanks - definitely think together about it (@westey-m you'll probably be interested to). BTW we also need to finalize the naming (QueryAsync) - IIRC @westey-m wasn't a fan; maybe let's do a meeting where we do a more holistic naming look; for the embedding generation integration changes, I plan on proposing replacing the existing APIs with SearchEmbeddingAsync (which accepts a raw embedding), vs. SearchAsync which would take a non-embedding. My main objective here is to make sure unsuspecting new users get to SearchAsync by default, and not to one of the more advanced/niche APIs. On that note, @adamsitnik can you put together a quick overview of what the non-vector search APIs are called in the different databases? If there's a standard/tendency that could inform our naming decision here and help us decide... |
The names of the APIs used are:
But most of them can be used for vector search as well (it's just a matter of different input for the same method) |
@adamsitnik one more thought... Do databases - and especially those that support only a single ordering property - generally allow specifying ascending vs. descending? Or is that more a thing that the databases with multiple properties support? |
They all (except of Pincone which does not support ordering at all) do support specifying ASC/DESC |
Fixed by #11112 |
We have seen requests for doing criteria filtering without vector similarity; that's important e.g. for synchronizing data, checking if records already exist in the database before updating them, and similar scenarios.
Once #10156 is done, doing this should be quite easy.
/cc @SteveSanderson
The text was updated successfully, but these errors were encountered: