diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 98649d2d1..dac20da62 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -28,6 +28,7 @@ ** xref:repositories/create-instances.adoc[] ** xref:repositories/query-methods-details.adoc[] ** xref:cassandra/repositories/query-methods.adoc[] +** xref:cassandra/repositories/vector-search.adoc[] ** xref:repositories/projections.adoc[] ** xref:repositories/custom-implementations.adoc[] ** xref:repositories/core-domain-events.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/cassandra/repositories/vector-search.adoc b/src/main/antora/modules/ROOT/pages/cassandra/repositories/vector-search.adoc new file mode 100644 index 000000000..2a850343d --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/cassandra/repositories/vector-search.adoc @@ -0,0 +1,8 @@ +:vector-search-intro-include: data-cassandra::partial$vector-search-intro-include.adoc +:vector-search-model-include: data-cassandra::partial$vector-search-model-include.adoc +:vector-search-repository-include: data-cassandra::partial$vector-search-repository-include.adoc +:vector-search-scoring-include: data-cassandra::partial$vector-search-scoring-include.adoc +:vector-search-method-derived-include: data-cassandra::partial$vector-search-method-derived-include.adoc +:vector-search-method-annotated-include: data-cassandra::partial$vector-search-method-annotated-include.adoc + +include::{commons}@data-commons::page$repositories/vector-search.adoc[] diff --git a/src/main/antora/modules/ROOT/partials/vector-search-intro-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-intro-include.adoc new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-intro-include.adoc @@ -0,0 +1 @@ + diff --git a/src/main/antora/modules/ROOT/partials/vector-search-method-annotated-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-method-annotated-include.adoc new file mode 100644 index 000000000..1cb10a0de --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-method-annotated-include.adoc @@ -0,0 +1,19 @@ +.Using `@Query` +==== +[source,java] +---- +interface CommentRepository extends Repository { + + @Query(""" + SELECT id, description, country, similarity_cosine(embedding,:embedding) AS score + FROM comments + ORDER BY embedding ANN OF :embedding LIMIT :limit + """) + SearchResults searchAnnotatedByEmbeddingNear(Vector embedding, Limit limit); +} +---- +==== + +Cassandra does not allow to limit search results by their score. +Declared search methods can include a `score` projection column if you wish to return the score value. +You can declare a `ScoringFunction` argument to specify which scoring function to use to calculate similarity. diff --git a/src/main/antora/modules/ROOT/partials/vector-search-method-derived-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-method-derived-include.adoc new file mode 100644 index 000000000..7d6b60646 --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-method-derived-include.adoc @@ -0,0 +1,16 @@ +.Using `Near` and `Within` Keywords in Repository Search Methods +==== +[source,java] +---- +interface CommentRepository extends Repository { + + List searchByEmbeddingNear(Vector vector); + + SearchResults searchByEmbeddingNear(Vector vector, ScoringFunction function); + +} +---- +==== + +Cassandra does not allow to limit search results by their score. +You can declare a `ScoringFunction` argument to specify which scoring function to use to calculate similarity. diff --git a/src/main/antora/modules/ROOT/partials/vector-search-model-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-model-include.adoc new file mode 100644 index 000000000..4035d8aa1 --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-model-include.adoc @@ -0,0 +1,19 @@ +==== +[source,java] +---- +class Comment { + + @Id String id; + String country; + String comment; + + @VectorType(dimensions = 5) + @SaiIndexed + Vector embedding; + + // getters, setters, … +} +---- +==== + +`@VectorType` and `@SaiIndexed` annotations are used to help with schema generation and type hints. diff --git a/src/main/antora/modules/ROOT/partials/vector-search-repository-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-repository-include.adoc new file mode 100644 index 000000000..46e15ce47 --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-repository-include.adoc @@ -0,0 +1,13 @@ +.Using `SearchResults` in a Repository Search Method +==== +[source,java] +---- +interface CommentRepository extends Repository { + + SearchResults searchByEmbeddingNear(Vector vector, ScoringFunction function, Limit limit); + +} + +SearchResults results = repository.searchByEmbeddingNear(Vector.of(…), ScoringFunction.cosine(), Limit.of(10)); +---- +==== diff --git a/src/main/antora/modules/ROOT/partials/vector-search-scoring-include.adoc b/src/main/antora/modules/ROOT/partials/vector-search-scoring-include.adoc new file mode 100644 index 000000000..91f6efc81 --- /dev/null +++ b/src/main/antora/modules/ROOT/partials/vector-search-scoring-include.adoc @@ -0,0 +1,20 @@ +Cassandra reports the score directly as similarity value through `similarity_euclidean`, `similarity_cosine`, and `similarity_dot_product` functions. + +.Using `ScoringFunction` in a Repository Search Methods +==== +[source,java] +---- +interface CommentRepository extends Repository { + + SearchResults searchByEmbeddingNear(Vector vector, ScoringFunction function); +} + +repository.searchByEmbeddingNear(Vector.of(…), ScoringFunction.cosine()); <1> + +repository.searchByEmbeddingNear(Vector.of(…), ScoringFunction.euclidean()); <2> +---- + +<1> Run a search and return results using the Cosine distance function to compute similarity. +<2> Run a search and return results using the Euclidean distance function to compute similarity. +==== +