Filtering in vector embedding search with Atlas

I’m trying to perform a vector embedding search with MongoDB Atlas Search.

I’m searching for clothes which I store in the Garment collection of my database. This is my Garment Schema:

const GarmentSchema = new Schema({
  name: {
    type: String,
    required: true,
  },
  brand: {
    type: String,
    required: true,
  },
  colors: {
    type: [String],
    required: true,
  },
  category: {
    type: String,
    required: true,
  },
  image_url: {
    type: String,
  },
  user: {
    type: Schema.Types.ObjectId,
    ref: "User",
  },
  embedding: {
    type: [Number],
    required: true,
  },
  createdAt: {
    type: String,
    required: true,
    index: true,
  },
});

This is based on the example MongoDB gives us for vector search, as it applies to my schema:

const matchingGarments = await collection.aggregate([
 {
          $search: {
            index: "default",
            knnBeta: {
              vector: embedding,
              path: "embedding",
              k: 5,
            },
          },
        },
      ])
      .toArray();

However, I would like to query by “top” or “bottom” so I added the match field, and Atlas search requires that if using knnBeta the $search query be first (or it returns an error) so I wrote it like this:

const matchingGarments = await collection
      .aggregate([
        {
          $search: {
            index: "default",
            knnBeta: {
              vector: embedding,
              path: "embedding",
              k: 5,
            },
          },
        },
        {
          $match: {
            category,
          },
        },
      ])
      .toArray();

However, I tested it to realize that it doesn’t actually make a difference because it’s still querying the top 5 results and then splitting them up based on the category so I could end up with 4 tops and 1 bottom regardless of the category I specify. I would like to get the top 5 bottoms that match when I input the category as “bottom” and the top 5 tops when I input “top”.

Is there any way to do this? Any input is really appreciated.

Update: This worked for me

const  matchingGarments = await collection
      .aggregate([
        {
          $search: {
            index: "default",
            knnBeta: {
              vector: embedding,
              path: "embedding",
              k: 5,
              filter: {
                text: {
                  query: category,
                  path: "category",
                },
              },
            },
          },
        },
      ])
      .toArray();

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.