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

如何在Prisma中获取列表首元素优化Next.js API性能

问题

在Next.js项目中,通过API路由使用Prisma获取设备列表时,每个设备的brand属性携带大量图片数据,导致JSON payload过大,影响应用性能。需要优化查询逻辑,仅返回每个brand的第一张图片,以此减小payload体积、提升用户体验。

相关Prisma模型(简化)

model Equipment {
  id            Int      @id @default(autoincrement())
  createdAt     DateTime @default(now()) @map("created_at")
  updatedAt     DateTime @updatedAt @map("updated_at")
  title         String   @db.VarChar(255)
  // 省略其他属性
  brand         Brand?           @relation(fields: [brandId], references: [id], onDelete: Cascade)
  brandId       Int?             @map("brand_id")
  images        EquipmentImage[]

  @@map("equipments")
}

当前查询代码

const equipments = await prisma.equipment.findMany({
    where: {
      published: true,
      category: {
        ...(slug && {
          slug: slug as string,
        }),
      },
    },
    include: {
      subcategory: {
        select: {
          id: true,
          slug: true,
          category: {
            select: {
              slug: true,
            },
          },
        },
      },
      images: true,
      brand: {
        select: {
          id: true,
          images: true, // 需要修改的部分
        },
      },
    },
  });

问题表现

返回的设备数据中,brand.images包含多张图片,示例片段如下:

{
  "id": 66,
  "title": "SY16C",
  "brand": {
    "id": 1,
    "images": [
      { "id": 16, "fileName": "SANY-4tu5s2li.png", /* 其他图片字段 */ },
      { "id": 29, "fileName": "SANY-nwffhrfd.jpeg", /* 其他图片字段 */ },
      // 更多图片数据
    ]
  }
}

解决方案

提供两种实用实现方案,按需选择:

方案1:通过Prisma查询直接限制图片数量

利用Prisma关联查询的take参数,直接从数据库层面只获取brand的第一张图片,配合orderBy可确保取到特定排序的图片(比如最早创建的)。

修改后的查询代码:

const equipments = await prisma.equipment.findMany({
    where: {
      published: true,
      category: {
        ...(slug && {
          slug: slug as string,
        }),
      },
    },
    include: {
      subcategory: {
        select: {
          id: true,
          slug: true,
          category: {
            select: {
              slug: true,
            },
          },
        },
      },
      images: true,
      brand: {
        select: {
          id: true,
          images: {
            take: 1, // 仅获取第一张图片
            orderBy: { createdAt: 'asc' } // 可选:按创建时间升序,保证取到固定的首张图片
          },
        },
      },
    },
  });

此方案返回的brand.images是仅含单张图片的数组,若需单个对象而非数组,可结合方案2的后处理逻辑。

方案2:查询后处理数据结构

如果需要调整返回的数据结构(比如将图片数组转为单个对象),可在查询完成后遍历设备列表,修改brand字段:

// 原查询逻辑不变,先获取完整数据
const equipments = await prisma.equipment.findMany({
    where: {
      published: true,
      category: {
        ...(slug && {
          slug: slug as string,
        }),
      },
    },
    include: {
      subcategory: {
        select: {
          id: true,
          slug: true,
          category: {
            select: {
              slug: true,
            },
          },
        },
      },
      images: true,
      brand: {
        select: {
          id: true,
          images: true,
        },
      },
    },
  });

// 处理数据,仅保留brand的第一张图片并调整结构
const processedEquipments = equipments.map(equipment => {
  if (!equipment.brand) return equipment;

  return {
    ...equipment,
    brand: {
      ...equipment.brand,
      image: equipment.brand.images[0] || null, // 将数组转为单个image对象
      images: undefined // 移除原图片数组
    }
  };
});

这种方式适合需要前端直接使用单个图片对象的场景,减少前端额外处理步骤。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:47:03