Florian
CCConvex Community
•Created by Florian on 5/27/2025 in #support-community
Vector Search with relational filter
Given this schema, how do I only retrieve embeddings for notes that belong to this particular user?
Do I need to put the
userId
into the embedding table as well?
import { authTables } from "@convex-dev/auth/server";
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
const schema = defineSchema({
...authTables,
notes: defineTable({
title: v.string(),
body: v.string(),
userId: v.id("users"),
}).index("by_userId", ["userId"]),
embeddings: defineTable({
content: v.string(),
embedding: v.array(v.float64()),
noteId: v.id("notes"),
})
.index("by_noteId", ["noteId"])
.vectorIndex("by_embedding", {
vectorField: "embedding",
dimensions: 1536,
filterFields: ["noteId"],
}),
});
export default schema;
import { authTables } from "@convex-dev/auth/server";
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
const schema = defineSchema({
...authTables,
notes: defineTable({
title: v.string(),
body: v.string(),
userId: v.id("users"),
}).index("by_userId", ["userId"]),
embeddings: defineTable({
content: v.string(),
embedding: v.array(v.float64()),
noteId: v.id("notes"),
})
.index("by_noteId", ["noteId"])
.vectorIndex("by_embedding", {
vectorField: "embedding",
dimensions: 1536,
filterFields: ["noteId"],
}),
});
export default schema;
10 replies
CCConvex Community
•Created by Florian on 5/21/2025 in #support-community
http request blocked by cors
Any idea why my request from localhost:3000 is still blocked by CORS? I copied the headers from a Convex sample.
I can call it from Postman but not React.
import { openai } from "@ai-sdk/openai";
import { getAuthUserId } from "@convex-dev/auth/server";
import { Message, streamText } from "ai";
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/api/chat",
method: "POST",
handler: httpAction(async (ctx, req) => {
const userId = await getAuthUserId(ctx);
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { messages } = await req.json();
const lastMessages = messages.slice(-30) as Message[];
const result = streamText({
model: openai("gpt-4o"),
messages: lastMessages,
});
return result.toDataStreamResponse({
headers: new Headers({
"Access-Control-Allow-Origin": "*",
Vary: "origin",
}),
});
}),
});
http.route({
path: "/api/chat",
method: "OPTIONS",
handler: httpAction(async (_, request) => {
const headers = request.headers;
if (
headers.get("Origin") !== null &&
headers.get("Access-Control-Request-Method") !== null &&
headers.get("Access-Control-Request-Headers") !== null
) {
return new Response(null, {
headers: new Headers({
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type, Digest",
"Access-Control-Max-Age": "86400",
}),
});
} else {
return new Response();
}
}),
});
export default http;
import { openai } from "@ai-sdk/openai";
import { getAuthUserId } from "@convex-dev/auth/server";
import { Message, streamText } from "ai";
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/api/chat",
method: "POST",
handler: httpAction(async (ctx, req) => {
const userId = await getAuthUserId(ctx);
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { messages } = await req.json();
const lastMessages = messages.slice(-30) as Message[];
const result = streamText({
model: openai("gpt-4o"),
messages: lastMessages,
});
return result.toDataStreamResponse({
headers: new Headers({
"Access-Control-Allow-Origin": "*",
Vary: "origin",
}),
});
}),
});
http.route({
path: "/api/chat",
method: "OPTIONS",
handler: httpAction(async (_, request) => {
const headers = request.headers;
if (
headers.get("Origin") !== null &&
headers.get("Access-Control-Request-Method") !== null &&
headers.get("Access-Control-Request-Headers") !== null
) {
return new Response(null, {
headers: new Headers({
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type, Digest",
"Access-Control-Max-Age": "86400",
}),
});
} else {
return new Response();
}
}),
});
export default http;
28 replies