javacassandranosqldatastax-astravector-search

How to INSERT a vector into Cassandra with Java?


I'm having trouble mapping a Java Vector type to my Cassandra table (Astra DB) in Java. The idea is to query by an ANN with Vector Search to return movie recommendations.

Here is my table definition:

CREATE TABLE movies (
  movie_id INT PRIMARY KEY,
  title TEXT,
  release_date DATE,
  movie_vector vector<float,7>);

Which maps to the class:

public class Movie {
    private int movieId;
    private String title;
    private LocalDate releaseDate;
    private CqlVector<Float> vector;

(complete w/ getters & setters)

And its properties get bound to a prepared statement with this CQL:

private final static String strCQLINSERT = "INSERT INTO movies "
        + "(movie_id,title,release_date,movie_vector) "
        + "VALUES (?,?,?,?)";

I then define a vector from an array of float using the Java Vector API, and then try to map that into my class.

Movie movie = new Movie();
// setting other properties on movie here
// ...
// create vector locally
float[] fltVector = {collectionId,genre1,genre2,genre3,popularity,rating,votes};
FloatVector vector = FloatVector.fromArray(FloatVector.SPECIES_MAX,fltVector,0);
// map vector to class
movie.setVector(vector);

When setting to the vector property (of type CqlVector) on my Movie class, I get this error:

The method newInstance in the type CqlVector is not applicable for the arguments FloatVector

I've also tried using the CqlVector type's newInstance method, but that doesn't seem to work, either. How can I map the fltVector to my table so that I can INSERT data?


Solution

  • So working with vector datatypes is a realtively new thing in both Java and Cassandra. In fact, as of right now, the CqlVector type is only valid in Astra DB, and the Java FloatVector type doesn't match it.

    That being said, there are a few ways to instantiate a new CqlVector object. The newInstance method accepts either a List<Float> or a String representation of the vector. The String representation can be tough to get right, so going the List<Float> route is probably the easiest path:

    List<Float> vectorListFloat = new ArrayList<>();
    
    vectorListFloat.add(collectionId);
    vectorListFloat.add(genre1);
    vectorListFloat.add(genre2);
    vectorListFloat.add(genre3);
    vectorListFloat.add(popularity);
    vectorListFloat.add(voteAverage);
    vectorListFloat.add(voteCount);
    
    CqlVector cqlVector = CqlVector.newInstance(vectorListFloat);
    

    With the cqlVector object instantated from newInstance(vectorListFloat), this should now work:

    movie.setVector(cqlVector);