Status: PREVIEW / proof-of-concept. Versioned 0.x-preview, not
1.0.0-beta.1 like every other package in this repo, on purpose - see
Why "preview" and not "beta" below. It works
(verified against a real Qdrant container, not asserted), but it exists to
answer a research question - "is talking to Qdrant directly simpler and
safer than going through Microsoft.Extensions.VectorData?" - not as a
fully-considered, general-purpose package yet. Read this whole file before
using it for anything beyond that question.
dotnet add package Xfty.VectorDatabases.QdrantQdrantPersistenceGateway implements XFTY's IPersistenceGateway,
inserting RecordProvider-generated records into a real Qdrant collection
through Qdrant.Client directly - no Microsoft.Extensions.VectorData
(MEVD), no Semantic Kernel connector at all. It builds PointStructs and a
Dictionary-style payload by hand via reflection
(QdrantRecordReflection), rather than getting that mapping from a shared
abstraction. Depends only on Qdrant's own stable client (Qdrant.Client,
1.19.0) - nothing preview, nothing Semantic-Kernel-branded.
There's also a separate package,
Xfty.VectorDatabases.MicrosoftExtensionsVectorData,
doing the same job through Microsoft's VectorStore abstraction instead of
Qdrant's client directly - its own package on purpose, so depending on this
one never pulls in MEVD or a Semantic-Kernel-branded connector this class
doesn't use. See roadmap/vector-databases.md
for the full comparison between the two approaches, including the one real,
concrete difference the comparison turned up (a schema-Type gotcha unique
to the MEVD path).
- The id field must be
Guid(orGuid?). Qdrant's client has no string overload for a point id at all -PointIdonly acceptsGuidorulong- so this is a real constraint of Qdrant itself, not an artifact of any particular library sitting in front of it.QdrantRecordReflection.RequireGuidKeythrows a clearNotSupportedExceptionat insert time rather than letting aCS0029-style failure or Qdrant's own opaque error surface instead. - Exactly one
float[]property is treated as the vector field, found by reflection (the first property of that exact type). A record with twofloat[]properties has its second one silently treated as an ordinary payload field; a record with none throwsInvalidOperationExceptionfrom.First(). - Every record of the same CLR type in one
Insertcall is assumed to share one vector dimensionality, read from the first record in the group. - One Qdrant collection per CLR type name (
recordType.Name, unqualified - no namespace). Two distinct record types that happen to share a short name would collide into the same collection. - Hardcodes
Distance.Cosinefor every collection it creates - no way to choose a different distance function or index kind. - Payload mapping only supports
string/bool/int/long/float/doubledata properties (a plainswitchon the CLR value) - anything else throws a clearNotSupportedExceptionrather than failing inside Qdrant's client with a less obvious error. - Insert-only. Matches
IPersistenceGateway's own single-method contract - no read, search, or delete surface. - Only covered by CI when a Docker-capable runner is present
(
[Trait("Category", "Docker")], same opt-in pattern as the Postgres tier inXfty.EntityFrameworkCore.Test) - it skips rather than fails without Docker.
Every other package in this solution (Xfty, Xfty.EntityFrameworkCore,
Xfty.Bogus, Xfty.VectorDatabases) is 1.0.0-beta.1 - a considered,
reasonably general-purpose surface with real test coverage. This package is
one gateway class, one demo type, one test, built specifically to answer a
comparison question - see roadmap/vector-databases.md.
Several of the assumptions above are real limitations rather than
deliberate design choices, and it has not been used against an actual
project's schema. A 0.x-preview version says exactly that.
- Support
ulongkeys, not justGuid. - Discover the vector field by an explicit convention (an attribute, or a
config lambda) instead of "the first
float[]property found by reflection." - Validate that every record in a batch shares one vector dimensionality up front, with a clear XFTY-side error instead of an opaque one from Qdrant.
- Expose
Distance/index-kind configuration instead of the hardcoded default. - Widen the payload mapping past
string/bool/int/long/float/double, or decide that's a fine permanent limitation.
See also: docs/roadmap/vector-databases.md, Xfty.VectorDatabases.MicrosoftExtensionsVectorData.