Part 5: Advanced Querying, Aggregations, and Production Best Practices

Introduction

We've covered the fundamentals of Prisma ORM, but production applications require more sophisticated techniques. In this final part, I'll share advanced patterns I've learned from building and scaling production systems with TypeScript, Prisma, and PostgreSQL.

These aren't theoretical examples—every technique here comes from real challenges I've faced: optimizing slow queries, implementing search functionality, handling complex aggregations, and ensuring production reliability.

Advanced Filtering and Querying

Complex Nested Filters

In a content management system I built, I needed to find posts with specific criteria across multiple relationships:

// Find published posts by active authors who have verified emails
// and posts must have at least 2 approved comments with tags 'typescript' or 'database'
const posts = await prisma.post.findMany({
  where: {
    published: true,
    author: {
      isActive: true,
      emailVerified: true,
      role: {
        in: ['ADMIN', 'EDITOR']
      }
    },
    comments: {
      some: {
        approved: true,
        content: {
          contains: 'great',
          mode: 'insensitive'
        }
      }
    },
    tags: {
      some: {
        slug: {
          in: ['typescript', 'database']
        }
      }
    },
    viewCount: {
      gte: 100
    }
  },
  include: {
    author: {
      select: {
        id: true,
        name: true,
        email: true
      }
    },
    tags: true,
    _count: {
      select: {
        comments: true
      }
    }
  },
  orderBy: [
    { viewCount: 'desc' },
    { createdAt: 'desc' }
  ]
});

Using NOT, AND, OR

Combining logical operators for complex business logic:

JSON Field Filtering (PostgreSQL)

Prisma supports PostgreSQL's JSON operations:

Aggregations and Grouping

Count, Sum, Average, Min, Max

Real example from an analytics dashboard I built:

Group By

Prisma's groupBy for aggregating data:

Monthly Statistics

Grouping by date parts using raw queries:

For a knowledge base I built, I implemented search using PostgreSQL's capabilities:

Advanced Full-Text Search with Raw SQL

For better performance and features:

Create a migration to set up full-text search:

Use it:

Raw SQL Queries

When to Use Raw SQL

I use raw SQL for:

  1. Complex analytical queries

  2. Database-specific features

  3. Performance-critical operations

  4. Legacy database integration

Typed Raw Queries

Safe Parameterization

Execute Raw (for non-SELECT queries)

Optimistic Concurrency Control

Preventing race conditions with version fields:

Soft Deletes

Instead of actually deleting records, mark them as deleted:

Connection Pooling and Performance

Database Connection Best Practices

Connection Pool Configuration

Query Optimization

Data Seeding

Production-like seed script I use:

Add to package.json:

Run seed:

Middleware and Logging

Query Logging Middleware

Soft Delete Middleware

Production Deployment Checklist

Based on my production deployments:

1. Environment Variables

2. Migration Strategy

3. Health Check Endpoint

4. Error Monitoring

5. Backup Strategy

Conclusion

This series covered everything from ORM fundamentals to production deployment. The techniques I've shared come from years of building and maintaining applications with Prisma, TypeScript, and PostgreSQL.

Key takeaways:

  • ORMs like Prisma provide type safety and developer productivity

  • Schema design impacts long-term maintainability

  • Migrations enable safe schema evolution

  • Advanced features like aggregations and full-text search unlock powerful capabilities

  • Production requires careful attention to performance, monitoring, and error handling

The stack we've explored—TypeScript, Prisma, and PostgreSQL—powers applications I maintain that handle millions of requests monthly. It's production-proven, developer-friendly, and continues to improve.

Resources


This concludes the ORM 101 series. All examples are based on real projects I've built and deployed to production. I hope this series helps you build better database-backed applications.

Last updated