Michael ReaM
Convex Community2y ago
9 replies
Michael Rea

Query Caching

I'm trying to understand which approach is best.

Do queries cache only on the level of the whole query?

----------
Option A:
//Schema
export const Chats = Table("chats", {
    userId: v.id("users"),
});

export const Messages = Table("messages", {
    userId: v.id("users"),
    chatId: v.id("chats"),
    role: v.string(),
    content: v.string(),
});


.......messages: Messages.table.index("by_chatId_userId", ["chatId", "userId"]),


export const get = queryWithUser({
    args: { chatId: v.id("chats") },
    handler: async (ctx, { chatId }): Promise<Doc<"messages">[]> => {
        const messages = await ctx.db
            .query("messages")
            .withIndex("by_chatId_userId", (q) => q.eq("chatId", chatId).eq("userId", ctx.userId))
            .order("desc")
            .collect();
            // .take(50);

        if (messages.length === 0) {
            return [];
        }
        return messages.reverse();
    },
});

----------
Option B:
export const Chats = Table("chats", {
    userId: v.id("users"),
    messageIds: v.array(v.id("messages")),
});

export const Messages = Table("messages", {
    userId: v.id("users"),
    chatId: v.id("chats"),
    role: v.string(),
    content: v.string(),
});


export const getByIds = queryWithUser({
    args: { messageIds: v.array(v.id("messages")) },
    handler: async (ctx, { messageIds }): Promise<Doc<"messages">[]> => {
        const messages = await Promise.all(
            messageIds.map((Id: Id<"messages">) => {
                return ctx.db.get(Id);
            })
        );
        if (messages.length === 0) {
            return [];
        }
        return messages.reverse();
    },
});


-----

Lets say a new message comes in, will option B be using the cached queries on each ID and get a non-cached for the new message?

Compared to option A (where I'm unclear) does that get all the messages without cache OR actually uses the cache under the hood?
Was this page helpful?