{"id":13467219,"url":"https://github.com/MihaelIsaev/FluentQuery","last_synced_at":"2025-03-26T01:30:28.034Z","repository":{"id":63918475,"uuid":"136088168","full_name":"MihaelIsaev/FluentQuery","owner":"MihaelIsaev","description":"🗃 Powerful and easy to use Swift Query Builder for Vapor 3.","archived":false,"fork":false,"pushed_at":"2020-03-21T07:43:57.000Z","size":181,"stargazers_count":149,"open_issues_count":3,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-29T20:36:03.807Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MihaelIsaev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-04T22:07:16.000Z","updated_at":"2024-10-08T06:28:08.000Z","dependencies_parsed_at":"2023-01-14T14:00:42.495Z","dependency_job_id":null,"html_url":"https://github.com/MihaelIsaev/FluentQuery","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MihaelIsaev%2FFluentQuery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MihaelIsaev%2FFluentQuery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MihaelIsaev%2FFluentQuery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MihaelIsaev%2FFluentQuery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MihaelIsaev","download_url":"https://codeload.github.com/MihaelIsaev/FluentQuery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245568554,"owners_count":20636803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T15:00:54.192Z","updated_at":"2025-03-26T01:30:27.739Z","avatar_url":"https://github.com/MihaelIsaev.png","language":"Swift","funding_links":[],"categories":["Libs","Utility [🔝](#readme)","HarmonyOS"],"sub_categories":["Utility","Windows Manager"],"readme":"[![Mihael Isaev](https://user-images.githubusercontent.com/1272610/40946272-af6396fa-686d-11e8-82af-192850fe3216.png)](http://mihaelisaev.com)\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg\" alt=\"MIT License\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swift.org\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/swift-4.1-brightgreen.svg\" alt=\"Swift 4.1\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://discord.gg/q5wCPYv\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/CLICK_HERE_TO_DISCUSS_THIS_LIB-SWIFT.STREAM-FD6F32.svg\" alt=\"Swift.Stream\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n### ⚠️ This lib is DEPRECATED ⚠️ please use [SwifQL](https://github.com/SwifQL/SwifQL) with [Bridges](https://github.com/SwifQL/Bridges)\n\n# Quick Intro\n\n```swift\nstruct PublicUser: Codable {\n    var name: String\n    var petName: String\n    var petType: String\n    var petToysQuantity: Int\n}\ntry FQL()\n    .select(all: User.self)\n    .select(\\Pet.name, as: \"petName\")\n    .select(\\PetType.name, as: \"petType\")\n    .select(.count(\\PetToy.id), as: \"petToysQuantity\")\n    .from(User.self)\n    .join(.left, Pet.self, where: \\Pet.id == \\User.idPet)\n    .join(.left, PetType.self, where: \\PetType.id == \\Pet.idType)\n    .join(.left, PetToy.self, where: \\PetToy.idPet == \\Pet.id)\n    .groupBy(\\User.id, \\Pet.id, \\PetType.id, \\PetToy.id)\n    .execute(on: conn)\n    .decode(PublicUser.self) // -\u003e Future\u003c[PublicUser]\u003e 🔥🔥🔥\n```\n\n# Intro\n\nIt's a swift lib that gives ability to build complex raw SQL-queries in a more easy way using KeyPaths. I call it **FQL** 😎\n\nBuilt for Vapor3 and depends on `Fluent` package because it uses `Model.reflectProperty(forKey:)` method to decode KeyPaths.\n\n### Install through Swift Package Manager\n\nEdit your `Package.swift`\n\n```swift\n//add this repo to dependencies\n.package(url: \"https://github.com/MihaelIsaev/FluentQuery.git\", from: \"0.4.30\")\n//and don't forget about targets\n//\"FluentQuery\"\n```\n### One more little intro\n\nI love to write raw SQL queries because it gives ability to flexibly use all the power of database engine.\n\nAnd Vapor's Fleunt allows you to do raw queries, but the biggest problem of raw queries is its hard to maintain them.\n\nI faced with that problem and I started developing this lib to write raw SQL queries in swift-way by using KeyPaths.\n\nAnd let's take a look what we have :)\n\n\n### How it works\n\nFirst of all you need to import the lib\n\n```swift\nimport FluentQuery\n```\n\nThen create `FQL` object, build your SQL query using methods described below and as first step just print it as a raw string\n\n```swift\nlet query = FQL()\n//some building\nprint(\"rawQuery: \\(query)\")\n```\n\n### Several examples\n\n#### 1. Simple\n\n```swift\n// SELECT * FROM \"User\" WHERE age \u003e 18\nlet fql = FQL().select(all: User.self)\n               .from(User.self)\n               .where(\\User.age \u003e 18)\n               .execute(on: conn)\n               .decode(User.self)\n```\n\n#### 2. Simple with join\n\n```swift\n// SELECT u.*, r.name as region FROM \"User\" as u WHERE u.age \u003e 18 LEFT JOIN \"UserRegion\" as r ON u.idRegion = r.id\nlet fql = FQL().select(all: User.self)\n               .select(\\UserRegion.name)\n               .from(User.self)\n               .where(\\User.age \u003e 18)\n               .join(.left, UserRegion.self, where: \\User.idRegion == \\UserRegion.id)\n               .execute(on: conn)\n               .decode(UserWithRegion.self)\n```\n\n#### 3. Medium 🙂 with query into jsonB obejcts\n\n```swift\n// SELECT (SELECT to_jsonb(u)) as user, (SELECT to_jsonb(r)) as region FROM \"User\" as u WHERE u.age \u003e 18 LEFT JOIN \"UserRegion\" as r ON u.idRegion = r.id\nlet fql = FQL().select(.row(User.self), as: \"user\")\n               .select(.row(UserRegion.self), as: \"region\")\n               .from(User.self)\n               .where(\\User.age \u003e 18)\n               .join(.left, UserRegion.self, where: \\User.idRegion == \\UserRegion.id)\n               .execute(on: conn)\n               .decode(UserWithRegion.self)\n// in this case UserWithRegion struct will look like this\nstruct UserWithRegion: Codable {\n    var user: User\n    var region: UserRegion\n}\n```\n\n#### 4. Complex\n\nLet's take a look how to use it with some example request\n\nImagine that you have a list of cars\n\nSo you have `Car` fluent model\n\n```swift\nfinal class Car: Model {\n  var id: UUID?\n  var year: String\n  var color: String\n  var engineCapacity: Double\n  var idBrand: UUID\n  var idModel: UUID\n  var idBodyType: UUID\n  var idEngineType: UUID\n  var idGearboxType: UUID\n}\n```\nand related models\n\n```swift\nfinal class Brand: Decodable {\n  var id: UUID?\n  var value: String\n}\nfinal class Model: Decodable {\n  var id: UUID?\n  var value: String\n}\nfinal class BodyType: Decodable {\n  var id: UUID?\n  var value: String\n}\nfinal class EngineType: Decodable {\n  var id: UUID?\n  var value: String\n}\nfinal class GearboxType: Decodable {\n  var id: UUID?\n  var value: String\n}\n```\n\nok, and you want to get every car as convenient codable model\n\n```swift\nstruct PublicCar: Content {\n  var id: UUID\n  var year: String\n  var color: String\n  var engineCapacity: Double\n  var brand: Brand\n  var model: Model\n  var bodyType: BodyType\n  var engineType: EngineType\n  var gearboxType: GearboxType\n}\n```\n\nHere's example request code for that situation\n\n```swift\nfunc getListOfCars(_ req: Request) throws -\u003e Future\u003c[PublicCar]\u003e {\n  return req.requestPooledConnection(to: .psql).flatMap { conn -\u003e EventLoopFuture\u003c[PublicCar]\u003e in\n      defer { try? req.releasePooledConnection(conn, to: .psql) }\n      return FQL()\n        .select(distinct: \\Car.id)\n        .select(\\Car.year, as: \"year\")\n        .select(\\Car.color, as: \"color\")\n        .select(\\Car.engineCapacity, as: \"engineCapacity\")\n        .select(.row(Brand.self), as: \"brand\")\n        .select(.row(Model.self), as: \"model\")\n        .select(.row(BodyType.self), as: \"bodyType\")\n        .select(.row(EngineType.self), as: \"engineType\")\n        .select(.row(GearboxType.self), as: \"gearboxType\")\n        .from(Car.self)\n        .join(.left, Brand.self, where: \\Brand.id == \\Car.idBrand)\n        .join(.left, Model.self, where: \\Model.id == \\Car.idModel)\n        .join(.left, BodyType.self, where: \\BodyType.id == \\Car.idBodyType)\n        .join(.left, EngineType.self, where: \\EngineType.id == \\Car.idEngineType)\n        .join(.left, GearboxType.self, where: \\GearboxType.id == \\Car.idGearboxType)\n        .groupBy(\\Car.id, \\Brand.id, \\Model.id, \\BodyType.id, \\EngineType.id, \\GearboxType.id)\n        .orderBy(.asc(\\Brand.value), .asc(\\Model.value))\n        .execute(on: conn)\n        .decode(PublicCar.self)\n  }\n}\n```\n\nHahah, that's cool right? 😃\n\nAs you can see we've build complex query to get all depended values and decoded postgres raw response to our codable model.\n\n\u003cdetails\u003e\n    \u003csummary\u003eBTW, this is a raw SQL equivalent\u003c/summary\u003e\n        \n    SELECT\n    DISTINCT c.id,\n    c.year,\n    c.color,\n    c.\"engineCapacity\",\n    (SELECT toJsonb(brand)) as \"brand\",\n    (SELECT toJsonb(model)) as \"model\",\n    (SELECT toJsonb(bt)) as \"bodyType\",\n    (SELECT toJsonb(et)) as \"engineType\",\n    (SELECT toJsonb(gt)) as \"gearboxType\"\n    FROM \"Cars\" as c\n    LEFT JOIN \"Brands\" as brand ON c.\"idBrand\" = brand.id\n    LEFT JOIN \"Models\" as model ON c.\"idModel\" = model.id\n    LEFT JOIN \"BodyTypes\" as bt ON c.\"idBodyType\" = bt.id\n    LEFT JOIN \"EngineTypes\" as et ON c.\"idEngineType\" = et.id\n    LEFT JOIN \"GearboxTypes\" as gt ON c.\"idGearboxType\" = gt.id\n    GROUP BY c.id, brand.id, model.id, bt.id, et.id, gt.id\n    ORDER BY brand.value ASC, model.value ASC\n\u003c/details\u003e\n\n\n### So why do you need to use this lib for your complex queries?\n\n#### The reason #1 is KeyPaths!\nIf you will change your models in the future you'll have to remember where you used links to this model properties and rewrite them manually and if you forgot one you will get headache in production. But with KeyPaths you will be able to compile your project only while all links to the models properties are up to date. Even better, you will be able to use `refactor` functionality of Xcode! 😄\n#### The reason #2 is `if/else` statements\nWith `FQL`'s query builder you can use `if/else` wherever you need. And it's super convenient to compare with using `if/else` while createing raw query string. 😉\n#### The reason #3\nIt is faster than multiple consecutive requests\n#### The reason #4\nYou can join on join on join on join on join on join 😁😁😁 \n\nWith this lib you can do real complex queries! 🔥 And you still flexible cause you can use if/else statements while building and even create two separate queries with the same basement using `let separateQuery = FQL(copy: originalQuery)` 🕺\n\n### Methods\n\nThe list of the methods which `FQL` provide with\n\n#### Select\nThese methods will add fields which will be used between `SELECT` and `FROM`\n\n`SELECT _here_some_fields_list_ FROM`\n\nSo to add what you want to select call these methods one by one\n\n| Method  | SQL equivalent |\n| ------- | -------------- |\n| .select(\"*\") | * |\n| .select(all: Car.self) | \"Cars\".* |\n| .select(all: someAlias) | \"some_alias\".* |\n| .select(\\Car.id) | \"Car\".id |\n| .select(someAlias.k(\\.id)) | \"some_alias\".id |\n| .select(distinct: \\Car.id) | DISTINCT \"Car\".id |\n| .select(distinct: someAlias.k(\\.id)) | DISTINCT \"some_alias\".id |\n| .select(.count(\\Car.id), as: \"count\") | COUNT(\"Cars\".id) as \"count\" |\n| .select(.sum(\\Car.value), as: \"sum\") | SUM(\"Cars\".value) as \"sum\" |\n| .select(.average(\\Car.value), as: \"average\") | AVG(\"Cars\".value) as \"average\" |\n| .select(.min(\\Car.value), as: \"min\") | MIN(\"Cars\".value) as \"min\" |\n| .select(.max(\\Car.value), as: \"max\") | MAX(\"Cars\".value) as \"max\" |\n| .select(.extract(.day, .timestamp, \\Car.createdAt), as: \"creationDay\") | EXTRACT(DAY FROM \"Cars\".value) as \"creationDay\" |\n| .select(.extract(.day, .interval, \"40 days 1 minute\"), as: \"creationDay\") | EXTRACT(DAY FROM INTERVAL '40 days 1 minute') as \"creationDay\" |\n| .select(by: .rowNumber, over: `FQOver`, as: \"rowNumber\") | rowNumber() OVER (partition BY `EXPRESSION` ORDER BY `SOMETHING`) as \"rowNumber\" |\n\n_BTW, read about aliases and `FQOver` below_\n\n#### Window functions\n\nIf you need to use window functions like rowNumber, rank, dense_rank, etc. like this\n```sql\nrowNumber() OVER(partition BY \"Record\".title, \"Record\".tag ORDER BY \"Record\".priority ASC) as \"rowNumber\"\n```\n(refer to: https://www.postgresql.org/docs/current/static/functions-window.html)\n\nthen you could build it like this\n```swift\nlet fqo = FQOver(.partition)\n            .by(\\Record.title, \\Record.tag)\n            .orderBy(.asc(\\Record.priority))\n```\nand then use it in your query like this\n```swift\nlet FQL()\n    .select(\\Record.id)\n    .select(by: .rowNumber, over: fqo, as: \"rowNumber\")\n    .from(Record.self)\n```\n\n#### From\n\n| Method  | SQL equivalent |\n| ------- | -------------- |\n| .from(\"Table\") | FROM \"Table\" |\n| .from(raw: \"Table\") | FROM Table |\n| .from(Car.self) | FROM \"Cars\" as \"_cars_\" |\n| .from(someAlias) | FROM \"SomeAlias\" as \"someAlias\" |\n\n#### Join\n\n`.join(FQJoinMode, Table, where: FQWhere)`\n\n```swift\nenum FQJoinMode {\n    case left, right, inner, outer\n}\n```\n\nAs `Table` you can put `Car.self` or `someAlias`\n\n_About `FQWhere` please read below_\n\n\n#### Where\n\n`.where(FQWhere)`\n\n##### You can write where predicate two ways\n\nFirst is object oriented\n```swift\nFQWhere(predicate).and(predicate).or(predicate).and(FQWhere).or(FQWhere)\n```\n\nSecond is predicate oriented\n\n_Example for AND statements_\n```swift\n\\User.email == \"sam@example.com\" \u0026\u0026 \\User.password == \"qwerty\" \u0026\u0026 \\User.active == true\n```\n\n_Example for OR statements_\n```swift\n\\User.email == \"sam@example.com\" || \\User.email == \"james@example.com\" || \\User.email == \"bob@example.com\"\n```\n\n_Example for  both AND and OR statements_\n```swift\n\\User.email == \"sam@example.com\" \u0026\u0026 FQWhere(\\User.role == .admin || \\User.role == .staff)\n```\n_What FQWhere() doing here? It groups OR statements into round brackets to achieve `a AND (b OR c)` sql code._\n\n##### What `predicate` is?\nIt may be `KeyPath operator KeyPath` or `KeyPath operator Value`\n\n`KeyPath` may be `\\Car.id` or `someAlias.k(\\.id)`\n\n`Value` may be any value like int, string, uuid, array, or even something optional or nil\n\nList of available operators you saw above in cheatsheet\n\nSome examples\n\n```swift\nFQWhere(someAlias.k(\\.deletedAt) == nil)\nFQWhere(someAlias.k(\\.id) == 12).and(\\Car.color ~~ [\"blue\", \"red\", \"white\"])\nFQWhere(\\Car.year == \"2018\").and(\\Brand.value !~ [\"Chevrolet\", \"Toyota\"])\nFQWhere(\\Car.year != \"2005\").and(someAlias.k(\\.engineCapacity) \u003e 1.6)\n```\n\n##### Where grouping example\n\nif you need to group predicates like\n\n```sql\n\"Cars\".\"engineCapacity\" \u003e 1.6 AND (\"Brands\".value LIKE '%YO%' OR \"Brands\".value LIKE '%ET')\n```\n\nthen do it like this\n\n```swift\nFQWhere(\\Car.engineCapacity \u003e 1.6).and(FQWhere(\\Brand.value ~~ \"YO\").or(\\Brand.value ~= \"ET\"))\n```\n\n##### Cheatsheet\n| Operator  | SQL equivalent | Description |\n| -- | --- | --- |\n| == | == / IS | Equals |\n| != | != / IS NOT| Not equals |\n| \u003e | \u003e | Greater than |\n| \u003c | \u003c | Less than |\n| \u003e= | \u003e= | Greater or equal |\n| \u003c= | \u003c= | Less or equal |\n| ~~ | IN () | In array |\n| !~ | NOT IN () | Not in array |\n| ~= | LIKE '%str' | Case sensitive text search |\n| ~~ | LIKE '%str%' | |\n| =~ | LIKE 'str%' | |\n| ~% | ILIKE '%str' | Case insensitive text search |\n| %% | ILIKE '%str%' | |\n| %~ | ILIKE 'str%' | |\n| !~= | NOT LIKE '%str' | Case sensitive text search where text not like string |\n| !~~ | NOT LIKE '%str%' | |\n| !=~ | NOT LIKE 'str%' | |\n| !~% | NOT ILIKE '%str' | Case insensitive text search where text not like string |\n| !%% | NOT ILIKE '%str%' | |\n| !%~ | NOT ILIKE 'str%' | |\n| ~~~ | @@ 'str' | Full text search |\n\n#### Having\n\n`.having(FQWhere)`\n\nAbout `FQWhere` you already read above, but as having calls after data aggregation you may additionally filter your results using aggreagate functions such as `SUM, COUNT, AVG, MIN, MAX`\n\n```swift\n.having(FQWhere(.count(\\Car.id) \u003e 0))\n//OR\n.having(FQWhere(.count(someAlias.k(\\.id)) \u003e 0))\n//and of course you an use .and().or().groupStart().groupEnd()\n```\n\n#### Group by\n\n```swift\n.groupBy(\\Car.id, \\Brand.id, \\Model.id)\n```\nor\n```swift\n.groupBy(FQGroupBy(\\Car.id).and(\\Brand.id).and(\\Model.id))\n```\nor\n```swift\nlet groupBy = FQGroupBy(\\Car.id)\ngroupBy.and(\\Brand.id)\ngroupBy.and(\\Model.id)\n.groupBy(groupBy)\n```\n\n#### Order by\n\n```swift\n.orderBy(FQOrderBy(\\Car.year, .asc).and(someAlias.k(\\.name), .desc))\n```\nor\n```swift\n.orderBy(.asc(\\Car.year), .desc(someAlias.k(\\.name)))\n```\n\n#### Offset\n\n| Method  | SQL equivalent |\n| ------- | -------------- |\n| .offset(0) | OFFSET 0 |\n\n#### Limit\n\n| Method  | SQL equivalent |\n| ------- | -------------- |\n| .limit(30) | LIMIT 30 |\n\n### JSON\n\nYou can build `json` on `jsonb` object by creating `FQJSON` instance\n\n| Instance  | SQL equivalent |\n| --------- | -------------- |\n| FQJSON(.normal) | build_json_object() |\n| FQJSON(.binary) | build_jsonb_object() |\n\nAfter creating instance you should fill it by calling `.field(key, value)` method like\n\n```swift\nFQJSON(.binary).field(\"brand\", \\Brand.value).field(\"model\", someAlias.k(\\.value))\n```\n\nas you may see it accepts keyPaths and aliased keypaths\n\nbut also it accept function as value, here's the list of available functions\n\n| Function  | SQL equivalent |\n| --------- | -------------- |\n| row(Car.self) | SELECT row_to_json(\"Cars\") |\n| row(someAlias) | SELECT row_to_json(\"some_alias\") |\n| extractEpochFromTime(\\Car.createdAt) | extract(epoch from \"Cars\".\"createdAt\") |\n| extractEpochFromTime(someAlias.k(\\.createdAt)) | extract(epoch from \"some_alias\".\"createdAt\") |\n| count(\\Car.id) | COUNT(\"Cars\".id) |\n| count(someAlias.k(\\.id)) | COUNT(\"some_alias\".id) |\n| countWhere(\\Car.id, FQWhere(\\Car.year == \"2012\")) | COUNT(\"Cars\".id) filter (where \"Cars\".year == '2012') |\n| countWhere(someAlias.k(\\.id), FQWhere(someAlias.k(\\.id) \u003e 12)) | COUNT(\"some_alias\".id) filter (where \"some_alias\".id \u003e 12) |\n\n\n### Aliases\n\n`FQAlias\u003cOriginalClass\u003e(aliasKey)` or `OriginalClass.alias(aliasKey)`\n\nAlso you can use static alias `OriginalClass.alias` if you need only one its variation\n\nAnd you can generate random alias `OriginalClass.randomAlias` but keep in mind that every call to `randomAlias` generates new alias as it's computed property\n\n#### What's that for?\n\nWhen you write complex query you may have several joins or subqueries to the same table and you need to use aliases for that like `\"Cars\" as c`\n\n#### Usage\n\nSo with FQL you can create aliases like this\n\n```swift\n//\"CarBrand\" as b\nlet aliasBrand = CarBrand.alias(\"b\")\n//\"CarModel\" as m\nlet aliasModel = CarModel.alias(\"m\")\n//\"EngineType\" as e\nlet aliasEngineType = EngineType.alias(\"e\")\n```\n\nand you can use KeyPaths of original tables referenced to these aliases like this\n\n```swift\naliasBrand.k(\\.id)\naliasBrand.k(\\.value)\naliasModel.k(\\.id)\naliasModel.k(\\.value)\naliasEngineType.k(\\.id)\naliasEngineType.k(\\.value)\n```\n\n### Executing query\n\n`.execute(on: PostgreSQLConnection)`\n\n```swift\ntry FQL().select(all: User.self).execute(on: conn)\n```\n\n### Decoding query\n\n`.decode(Decodable.Type, dateDecodingstrategy: JSONDecoder.DateDecodingStrategy?)`\n\n```swift\ntry FQL().select(all: User.self).execute(on: conn).decode(PublicUser.self)\n```\n\n### Custom DateDecodingStrategy\n\nBy default date decoding strategy is `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` which is compatible with postgres `timestamp`\n\nBut you can specify custom DateDecodingStrategy like this\n```swift\ntry FQL().select(all: User.self).execute(on: conn).decode(PublicUser.self, dateDecodingStrategy: .secondsSince1970)\n```\n\nor like this\n\n```swift\nlet formatter = DateFormatter()\nformatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\"\ntry FQL().select(all: User.self).execute(on: conn).decode(PublicUser.self, dateDecodingStrategy: .formatted(formatter))\n```\n\nor if you have two or more columns with different date format in the same model then you could create your own date formatter like described in [issue #3](https://github.com/MihaelIsaev/FluentQuery/issues/3#issuecomment-406801436)\n\n\n### Conslusion\n\nI hope that it'll be useful for someone.\n\nFeedback is really appreciated!\n\nAnd don't hesitate to asking me questions, I'm ready to help in [Vapor's discord chat](http://vapor.team) find me by @iMike nickname.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMihaelIsaev%2FFluentQuery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMihaelIsaev%2FFluentQuery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMihaelIsaev%2FFluentQuery/lists"}