You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中向DataLoader传递自定义对象参数?

对象作为DataLoader Key的问题解决

问题现象

尝试将包含postId和userId的对象作为DataLoader的key传入,自定义缓存键函数后仍触发报错:

driverError: error: invalid input syntax for type integer: "{\"postId\":317,\"userId\":2}"

错误原因

  1. 数据库查询参数错误:在批量加载函数batchLoadFn中,直接将对象数组keys传入In(),数据库驱动会自动把对象序列化为JSON字符串,而数据库期望接收整数类型的ID数组,导致类型不匹配报错。
  2. 缓存键函数未正确实现:默认的cacheKeyFn将对象作为缓存键,但JavaScript中对象是引用类型,即使内容完全相同的两个对象也会被视为不同的键,无法实现缓存复用;你尝试的自定义函数返回对象或自定义类实例,同样无法解决引用类型的缓存键识别问题。

正确解决方案

1. 修复批量查询逻辑

从keys数组中提取出postId和userId的纯值数组,再传入In()条件。

2. 实现正确的缓存键函数

返回一个唯一的字符串作为缓存键(比如userId|postId的拼接格式),确保内容相同的对象会生成完全一致的缓存键。

完整代码示例

// 自定义缓存键函数:返回字符串格式的唯一标识
function cacheKeyFn({ postId, userId }: { postId: number; userId: number }) {
  return `${userId}|${postId}`;
}

export const createUpvoteLoader = () => 
  new DataLoader<{ postId: number; userId: number }, Upvote | null, string>(
    async (keys) => {
      // 从keys数组中提取所有postId和userId的纯值数组
      const postIds = keys.map(key => key.postId);
      const userIds = keys.map(key => key.userId);

      // 查询符合条件的所有点赞记录
      const upvotes = await Upvote.findBy({
        postId: In(postIds),
        userId: In(userIds)
      });

      // 构建映射表,方便按key快速查找结果
      const upvoteMap: Record<string, Upvote> = {};
      upvotes.forEach(upvote => {
        upvoteMap[`${upvote.userId}|${upvote.postId}`] = upvote;
      });

      // 按传入keys的顺序返回对应结果,无匹配则返回null
      return keys.map(key => upvoteMap[`${key.userId}|${key.postId}`] ?? null);
    },
    { cacheKeyFn }
  );

额外说明

  • cacheKeyFn的返回值必须是可被Map正确识别为相同键的类型,字符串、数字等基本类型都适用,避免使用对象或自定义类实例。
  • 批量查询时必须明确提取ID纯值数组,不能直接将对象数组传入数据库查询条件,否则会触发类型转换错误。

内容的提问来源于stack exchange,提问作者jpr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:42:05