Search code examples
swiftvaporvapor-fluent

Why can't I use filter in custom controller with Vapor 4?


I want to add a route to get matched data by searching for a specific string. I added the route into routes(_:) in routes.swift.

import Fluent
import Vapor

func routes(_ app: Application) throws {
  // route "api/acronyms/search?term=The+string+searched
  app.get("search") { req -> EventLoopFuture<[Acronym]> in
    guard let searchTerm = req.query[String.self, at: "term"] else {
      throw Abort(.badRequest)
    }

    return Acronym.query(on: app.db)
      .group(.or) { group in
        group
          .filter(\.$short == searchTerm)
          .filter(\.$long == searchTerm)
      }
      .all()
  }
}

And this works. I want to move it into controller. So I created a handler function in the controller.

import Vapor
import Fluent

struct AcronymsController: RouteCollection {
  let app: Application

  func boot(routes: RoutesBuilder) throws {
    routes.get("search", use: search)
  }
  
  func search(req: Request) throws -> EventLoopFuture<[Acronym]> {
    guard let searchTerm = req.query[String.self, at: "term"] else {
            throw Abort(.badRequest)
          }

          return Acronym.query(on: app.db)
            .filter(\Acronym.$short == searchTerm)
            .filter(\Acronym.$long == searchTerm)
            .all()
  }
}

But I got Swift Compiler Error: Binary operator '==' cannot be applied to operands of type 'KeyPath<Acronym, FieldProperty<Acronym, String>>' and 'String'.

Why filter with operator == doesn't work in the controller?

Environment

  • Vapor 4.27.1 (toolbox 18.2.1)
  • Swift 5.2.4
  • macOS Catalina 10.15.6

Solution

  • You need to import Fluent in the controller file so the compiler can see the operator overloads fire the query