Vectors
Vectors are for finding things that are like a query rather than equal to it. You store an embedding under a key, and you search by handing over another embedding and asking what is closest.
strata vector collection create docs 3
strata vector upsert docs a 1,0,0
strata vector upsert docs b 0.9,0.1,0
strata vector query docs 1,0,0
KEY SCORE METADATA
a 1.0 -
b 0.993884 -
Results come back ranked, closest first, as key and score.
Collections fix the dimension
Unlike the other models, vectors need setting up. A collection is created with a name, a dimension, and a metric:
strata vector collection create docs 3 --metric cosine
created collection docs (3 dimensions, cosine)
The metric is cosine by default, with euclidean and dot-product available.
The dimension is fixed at creation and enforced on every write:
strata vector upsert docs bad 1,0
invalid_argument.engine.vector_dimension: vector dimension mismatch
That is the behaviour you want. A collection whose vectors have different widths cannot be searched meaningfully, so the error arrives at write time rather than as nonsense at query time.
strata vector collection stats docs reports the name, dimension, metric and
current count.
Let the collection embed your text
A collection can record the model that produces its vectors, and then take text instead of numbers.
strata vector collection create docs 1536 --embedding-model openai:text-embedding-3-small
created collection docs (1536 dimensions, cosine)
An existing collection can be told later:
strata vector collection set-embedding-model plain miniLM
updated collection plain: embedding model miniLM
With a model recorded, --text does the embedding on the way in and on the way
out, so the same words are never embedded two different ways:
strata vector upsert docs doc:1 --text "the cat sat on the mat"
strata vector query docs --text "where did the cat sit"
That is the point of recording the model rather than passing it per call.
Embedding the corpus with one model and the query with another returns
neighbours that are ranked and meaningless, and nothing about the numbers
themselves would tell you. vector collection list shows what each one records:
strata vector collection list
NAME DIMENSION METRIC COUNT EMBEDDING_MODEL
docs 1536 cosine 0 openai:text-embedding-3-small
plain 3 cosine 0 miniLM
Ask for text against a collection that records nothing and it says so rather than picking a model for you:
strata vector upsert nomodel a --text "hello"
failed_precondition.engine.embedding_model_missing: vector collection `nomodel`
records no embedding model, so text cannot be embedded for it; declare one with
`vector collection set-embedding-model nomodel <model>`, or pass a vector directly
A vector you pass yourself is never checked against the recorded model. Passing one is your statement that this model produced it.
Text writes call the provider, so they need a key and they cost what that
provider charges. Inference covers setting one up, and
strata inference status says which are ready.
Metadata and filtering
A vector can carry metadata, and a query can filter on it:
strata vector upsert docs a 1,0,0 --metadata '{"lang":"en","tier":1}'
The filter is more elaborate than it looks like it should be. Conditions are AND-composed, and each value is tagged with its type:
strata vector query docs 1,0,0 \
--filter '{"conditions":[{"field":"lang","op":"eq","value":{"type":"string","value":"en"}}]}'
eq is currently the only operator, so a filter is “all of these fields equal
these values”. There are no ranges, no negation and no OR.
Writing the plain form {"lang":"en"} fails, and the error names an internal
Rust type rather than the shape it wanted, so the structure above is worth
copying rather than deriving. Tracked as strata-core issue 3120.
The same filter shape drives bulk deletion:
strata vector delete-by-filter docs --filter '{"conditions":[...]}'
Upsert replaces the whole record
This is the one to know. upsert without --metadata does not leave the
existing metadata alone. It removes it.
strata vector upsert docs a 1,0,0 --metadata '{"lang":"en","tier":1}'
strata vector upsert docs a 0.5,0.5,0
strata vector get docs a
key a
vector_revision 2
version 5
embedding [0.5,0.5,0.0]
metadata -
The metadata column reads -: it is gone, and the command reported success.
Meanwhile update-metadata merges, leaving fields you did not mention
intact:
strata vector update-metadata docs a '{"lang":"de"}'
key a
vector_revision 2
version 5
embedding [1.0,0.0,0.0]
metadata {"lang":"de","tier":1}
So one half of the record patches and the other half replaces everything, and there is no command that updates an embedding alone. Re-embedding a document, which is the ordinary reason to touch a vector twice, means passing its metadata again or losing it.
Until that changes, read before you write, or keep the metadata somewhere you control. Also strata-core issue 3120.
Reading without searching
Not every access is a similarity search:
strata vector get docs a
strata vector keys docs
strata vector count docs
strata vector history docs a
query takes -k for the number of matches, defaulting to 10, and --as-of
to search the collection as it stood earlier.
Where to look next
Every vector command, with its parameters, return shape and error codes, is in the vector reference.