MongoDB Vector search Tutorial

Introduction

I have been working with mongodb for a while now, and for the past few days I have been trying to implement vector search in mongodb. but i was using prisma and i had no idea how to implement vector search while using Prisma. So spent some time reading the documentation, tinkering with the query by myself and was able to do implement it. So, this is a small tutorial on how to implement vector search in mongodb.

Adding MongoDB vector search index

  1. Create a new vector search index in MongoDB atlas or MongoDB shell or MongoDB compose ui. Create a new Vector search Index

  2. Add the fields that you want to index Configuration of fields to index

There are two types of fields you can add, 1. vector: This is used for fields you want to index for vector search. 2. filter: This is used for fields you want to filter on.

For my use case, I had notes schema, i wanted to index the embedding field for vector search and userId field for filtering.

Writing query

For context this is my notes schema in prisma, in that I have an embedding field which is an array of floats, and I want to search for notes based on the embedding vector.

model Notes {
  id              String   @id @default(auto()) @map("_id") @db.ObjectId
  userId          String   @db.ObjectId
  title           String
  content         String
  labels          String[]
  embedding       Float[]
  links           String[]
  imageUrls       String[]
  isPublic        Boolean? @default(false)
  participantsIds String[] @db.ObjectId
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  // Relations
  user         User   @relation(fields: [userId], references: [id])
  participants User[] @relation("NoteParticipants", fields: [participantsIds], references: [id])
}

For running the search here’s the query you need to perform:

    const notes = await this.prisma.$runCommandRaw({
      aggregate: "Notes",
      pipeline: [
        {
          $vectorSearch: {
            index: "default",
            path: "embedding",
            filter: {
              userId: {
                $eq: {
                  $oid: userId,
                },
              },
            },
            queryVector: queryEmbedding.embedding,
            numCandidates: 150,
            limit: 5,
          },
        },
        {
          $project: {
            _id: 1,
            content: 1,
            title: 1,
            score: {
              $meta: "vectorSearchScore",
            },
          },
        },
      ],
      cursor: {},
    });

In index field you have to put the name of the index you created in the first step, In aggregate you have to enter the name of the collection you want to search in, in this case it is Notes. In path you have to pass the embedding field you want to search on, in this case it is embedding. In filter you can pass the fields you want to filter on, in this case it is userId. In queryVector you have to pass the vector you want to search for, in this case it is queryEmbedding.embedding. In numCandidates you can specify how many candidates you want to consider for the search, in this case it is 150. In limit you can specify how many results you want to return, in this case it is 5.

References

MongoDB vector search

Conclusion

That’s it! You have successfully implemented vector search in mongodb using prisma. You can now use this query to search for notes based on the embedding vector. You can also modify the query to suit your needs, like changing the number of candidates or the limit of results.