- Use PostgreSQL document library
- Remove `isLegacy` property from profiles and listings
- Update Docker image parameters (v 3.1 is deployed as a container)
- Update dependencies
This commit was merged in pull request #42.
This commit is contained in:
2023-07-02 20:00:16 -04:00
committed by GitHub
parent f289bee79d
commit a89eff2363
23 changed files with 255 additions and 553 deletions

View File

@@ -1,5 +1,6 @@
module JobsJobsJobs.Profiles.Data
open BitBadger.Npgsql.FSharp.Documents
open JobsJobsJobs.Common.Data
open JobsJobsJobs.Domain
open JobsJobsJobs.Profiles.Domain
@@ -7,83 +8,63 @@ open Npgsql.FSharp
/// Count the current profiles
let count () =
dataSource ()
|> Sql.query
$"""SELECT COUNT(id) AS the_count FROM {Table.Profile} WHERE data @> '{{ "isLegacy": false }}'::jsonb"""
|> Sql.executeRowAsync (fun row -> row.int64 "the_count")
Count.all Table.Profile
/// Delete a profile by its ID
let deleteById citizenId = backgroundTask {
let! _ =
dataSource ()
|> Sql.query $"DELETE FROM {Table.Profile} WHERE id = @id"
|> Sql.parameters [ "@id", Sql.string (CitizenId.toString citizenId) ]
|> Sql.executeNonQueryAsync
()
}
let deleteById citizenId =
Delete.byId Table.Profile (CitizenId.toString citizenId)
/// Find a profile by citizen ID
let findById citizenId = backgroundTask {
match! dataSource () |> getDocument<Profile> Table.Profile (CitizenId.toString citizenId) with
| Some profile when not profile.IsLegacy -> return Some profile
| Some _
| None -> return None
}
let findById citizenId =
Find.byId<Profile> Table.Profile (CitizenId.toString citizenId)
/// Convert a data row to a profile for viewing
let private toProfileForView row =
{ Profile = toDocument<Profile> row
Citizen = toDocumentFrom<Citizen> "cit_data" row
Continent = toDocumentFrom<Continent> "cont_data" row
{ Profile = fromData<Profile> row
Citizen = fromDocument<Citizen> "cit_data" row
Continent = fromDocument<Continent> "cont_data" row
}
/// Find a profile by citizen ID for viewing (includes citizen and continent information)
let findByIdForView citizenId = backgroundTask {
let! tryCitizen =
dataSource ()
|> Sql.query $"""
SELECT p.*, c.data AS cit_data, o.data AS cont_data
FROM {Table.Profile} p
INNER JOIN {Table.Citizen} c ON c.id = p.id
INNER JOIN {Table.Continent} o ON o.id = p.data ->> 'continentId'
WHERE p.id = @id
AND p.data @> '{{ "isLegacy": false }}'::jsonb"""
|> Sql.parameters [ "@id", Sql.string (CitizenId.toString citizenId) ]
|> Sql.executeAsync toProfileForView
return List.tryHead tryCitizen
}
let findByIdForView citizenId =
Custom.single<ProfileForView>
$"SELECT p.*, c.data AS cit_data, o.data AS cont_data
FROM {Table.Profile} p
INNER JOIN {Table.Citizen} c ON c.id = p.id
INNER JOIN {Table.Continent} o ON o.id = p.data ->> 'continentId'
WHERE p.id = @id"
[ "@id", Sql.string (CitizenId.toString citizenId) ]
toProfileForView
/// Save a profile
let save (profile : Profile) =
dataSource () |> saveDocument Table.Profile (CitizenId.toString profile.Id) <| mkDoc profile
save Table.Profile (CitizenId.toString profile.Id) profile
/// Search profiles
let search (search : ProfileSearchForm) isPublic = backgroundTask {
let searches = [
if search.ContinentId <> "" then
"p.data @> @continent", [ "@continent", Sql.jsonb (mkDoc {| continentId = search.ContinentId |}) ]
"p.data @> @continent", [ "@continent", Query.jsonbDocParam {| continentId = search.ContinentId |} ]
if search.RemoteWork <> "" then
"p.data @> @remote", [ "@remote", Sql.jsonb (mkDoc {| isRemote = search.RemoteWork = "yes" |}) ]
"p.data @> @remote", [ "@remote", Query.jsonbDocParam {| isRemote = search.RemoteWork = "yes" |} ]
if search.Text <> "" then
"p.text_search @@ plainto_tsquery(@text_search)", [ "@text_search", Sql.string search.Text ]
]
let vizSql =
if isPublic then
sprintf "(p.data @> '%s'::jsonb OR p.data @> '%s'::jsonb)"
(mkDoc {| visibility = ProfileVisibility.toString Public |})
(mkDoc {| visibility = ProfileVisibility.toString Anonymous |})
(Configuration.serializer().Serialize {| visibility = ProfileVisibility.toString Public |})
(Configuration.serializer().Serialize {| visibility = ProfileVisibility.toString Anonymous |})
else sprintf "p.data ->> 'visibility' <> '%s'" (ProfileVisibility.toString Hidden)
let! results =
dataSource ()
|> Sql.query $"""
SELECT p.*, c.data AS cit_data, o.data AS cont_data
FROM {Table.Profile} p
INNER JOIN {Table.Citizen} c ON c.id = p.id
INNER JOIN {Table.Continent} o ON o.id = p.data ->> 'continentId'
WHERE p.data @> '{{ "isLegacy": false }}'::jsonb
AND {vizSql}
{searchSql searches}"""
|> Sql.parameters (searches |> List.collect snd)
|> Sql.executeAsync toProfileForView
Custom.list<ProfileForView>
$" SELECT p.*, c.data AS cit_data, o.data AS cont_data
FROM {Table.Profile} p
INNER JOIN {Table.Citizen} c ON c.id = p.id
INNER JOIN {Table.Continent} o ON o.id = p.data ->> 'continentId'
WHERE {vizSql}
{searchSql searches}"
(searches |> List.collect snd)
toProfileForView
return results |> List.sortBy (fun pfv -> (Citizen.name pfv.Citizen).ToLowerInvariant ())
}