Wrapped all Filter and Merge lambdas in a ReqlFunction1 constructor
(which made them work); fixed some ReQL logic errors; removed
RunListAsync extension and changed calls to RunResultAsync<* list>
This commit is contained in:
Daniel J. Summers 2016-09-18 22:20:10 -05:00
parent 3f9665a2e6
commit f4d520e34b
10 changed files with 92 additions and 93 deletions

View File

@ -385,7 +385,7 @@ type EditPostForm() =
member val PublishNow = true with get, set member val PublishNow = true with get, set
/// Fill the form with applicable values from a post /// Fill the form with applicable values from a post
member this.ForPost post = member this.ForPost (post : Post) =
this.Title <- post.Title this.Title <- post.Title
this.Permalink <- post.Permalink this.Permalink <- post.Permalink
this.Tags <- List.reduce (fun acc x -> sprintf "%s, %s" acc x) post.Tags this.Tags <- List.reduce (fun acc x -> sprintf "%s, %s" acc x) post.Tags

View File

@ -9,23 +9,23 @@ let private r = RethinkDb.Driver.RethinkDB.R
let private category (webLogId : string) (catId : string) = let private category (webLogId : string) (catId : string) =
r.Table(Table.Category) r.Table(Table.Category)
.Get(catId) .Get(catId)
.Filter(fun c -> c.["WebLogId"].Eq(webLogId)) .Filter(ReqlFunction1(fun c -> upcast c.["WebLogId"].Eq(webLogId)))
/// Get all categories for a web log /// Get all categories for a web log
let getAllCategories conn (webLogId : string) = let getAllCategories conn (webLogId : string) =
r.Table(Table.Category) r.Table(Table.Category)
.GetAll(webLogId).OptArg("index", "WebLogId") .GetAll(webLogId).OptArg("index", "WebLogId")
.OrderBy("Name") .OrderBy("Name")
.RunListAsync<Category>(conn) .RunResultAsync<Category list>(conn)
|> await |> await
|> Seq.toList
/// Get a specific category by its Id /// Get a specific category by its Id
let tryFindCategory conn webLogId catId : Category option = let tryFindCategory conn webLogId catId : Category option =
match (category webLogId catId) (category webLogId catId)
.RunAtomAsync<Category>(conn) |> await |> box with .RunResultAsync<Category>(conn)
| null -> None |> await
| cat -> Some <| unbox cat |> box
|> function null -> None | cat -> Some <| unbox cat
/// Add a category /// Add a category
let addCategory conn (cat : Category) = let addCategory conn (cat : Category) =
@ -81,9 +81,8 @@ let deleteCategory conn (cat : Category) =
r.Table(Table.Post) r.Table(Table.Post)
.GetAll(cat.WebLogId).OptArg("index", "WebLogId") .GetAll(cat.WebLogId).OptArg("index", "WebLogId")
.Filter(ReqlFunction1(fun p -> upcast p.["CategoryIds"].Contains(cat.Id))) .Filter(ReqlFunction1(fun p -> upcast p.["CategoryIds"].Contains(cat.Id)))
.RunCursorAsync<Post>(conn) .RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.toList
|> List.iter (fun post -> let newCats = |> List.iter (fun post -> let newCats =
{ PostCategoriesUpdateRecord.CategoryIds = post.CategoryIds { PostCategoriesUpdateRecord.CategoryIds = post.CategoryIds
|> List.filter (fun c -> c <> cat.Id) } |> List.filter (fun c -> c <> cat.Id) }
@ -101,6 +100,6 @@ let deleteCategory conn (cat : Category) =
let tryFindCategoryBySlug conn (webLogId : string) (slug : string) = let tryFindCategoryBySlug conn (webLogId : string) (slug : string) =
r.Table(Table.Category) r.Table(Table.Category)
.GetAll(r.Array(webLogId, slug)).OptArg("index", "Slug") .GetAll(r.Array(webLogId, slug)).OptArg("index", "Slug")
.RunCursorAsync<Category>(conn) .RunResultAsync<Category list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead

View File

@ -5,7 +5,3 @@ open RethinkDb.Driver.Ast
open RethinkDb.Driver.Net open RethinkDb.Driver.Net
let await task = task |> Async.AwaitTask |> Async.RunSynchronously let await task = task |> Async.AwaitTask |> Async.RunSynchronously
type ReqlExpr with
/// Run a SUCCESS_ATOM response that returns multiple values
member this.RunListAsync<'T> (conn : IConnection) = this.RunAtomAsync<System.Collections.Generic.List<'T>> conn

View File

@ -9,7 +9,7 @@ let private r = RethinkDb.Driver.RethinkDB.R
let tryFindPageById conn webLogId (pageId : string) includeRevs = let tryFindPageById conn webLogId (pageId : string) includeRevs =
let pg = r.Table(Table.Page) let pg = r.Table(Table.Page)
.Get(pageId) .Get(pageId)
match includeRevs with true -> pg.RunAtomAsync<Page>(conn) | _ -> pg.Without("Revisions").RunAtomAsync<Page>(conn) match includeRevs with true -> pg.RunResultAsync<Page>(conn) | _ -> pg.Without("Revisions").RunResultAsync<Page>(conn)
|> await |> await
|> box |> box
|> function |> function
@ -22,9 +22,9 @@ let tryFindPageByPermalink conn (webLogId : string) (permalink : string) =
r.Table(Table.Page) r.Table(Table.Page)
.GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink") .GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink")
.Without("Revisions") .Without("Revisions")
.RunCursorAsync<Page>(conn) .RunResultAsync<Page list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead
/// Get a list of all pages (excludes page text and revisions) /// Get a list of all pages (excludes page text and revisions)
let findAllPages conn (webLogId : string) = let findAllPages conn (webLogId : string) =
@ -32,9 +32,8 @@ let findAllPages conn (webLogId : string) =
.GetAll(webLogId).OptArg("index", "WebLogId") .GetAll(webLogId).OptArg("index", "WebLogId")
.OrderBy("Title") .OrderBy("Title")
.Without("Text", "Revisions") .Without("Text", "Revisions")
.RunListAsync<Page>(conn) .RunResultAsync<Page list>(conn)
|> await |> await
|> Seq.toList
/// Add a page /// Add a page
let addPage conn (page : Page) = let addPage conn (page : Page) =

View File

@ -15,25 +15,24 @@ let private toPostList conn pageNbr nbrPerPage (filter : ReqlExpr) =
filter filter
.OrderBy(r.Desc("PublishedOn")) .OrderBy(r.Desc("PublishedOn"))
.Slice((pageNbr - 1) * nbrPerPage, pageNbr * nbrPerPage) .Slice((pageNbr - 1) * nbrPerPage, pageNbr * nbrPerPage)
.RunListAsync<Post>(conn) .RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.toList
/// Shorthand to get a newer or older post /// Shorthand to get a newer or older post
let private adjacentPost conn post (theFilter : ReqlExpr -> obj) (sort : obj) = let private adjacentPost conn (post : Post) (theFilter : ReqlExpr -> obj) (sort : obj) =
(publishedPosts post.WebLogId) (publishedPosts post.WebLogId)
.Filter(theFilter) .Filter(theFilter)
.OrderBy(sort) .OrderBy(sort)
.Limit(1) .Limit(1)
.RunListAsync<Post>(conn) .RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead
/// Find a newer post /// Find a newer post
let private newerPost conn post theFilter = adjacentPost conn post theFilter <| r.Asc "publishedOn" let private newerPost conn post theFilter = adjacentPost conn post theFilter <| r.Asc "PublishedOn"
/// Find an older post /// Find an older post
let private olderPost conn post theFilter = adjacentPost conn post theFilter <| r.Desc "publishedOn" let private olderPost conn post theFilter = adjacentPost conn post theFilter <| r.Desc "PublishedOn"
/// Get a page of published posts /// Get a page of published posts
let findPageOfPublishedPosts conn webLogId pageNbr nbrPerPage = let findPageOfPublishedPosts conn webLogId pageNbr nbrPerPage =
@ -83,89 +82,94 @@ let findPageOfAllPosts conn (webLogId : string) pageNbr nbrPerPage =
.GetAll(webLogId).OptArg("index", "WebLogId") .GetAll(webLogId).OptArg("index", "WebLogId")
.OrderBy(r.Desc("PublishedOn")) .OrderBy(r.Desc("PublishedOn"))
.Slice((pageNbr - 1) * nbrPerPage, pageNbr * nbrPerPage) .Slice((pageNbr - 1) * nbrPerPage, pageNbr * nbrPerPage)
.RunListAsync<Post>(conn) .RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.toList
/// Try to find a post by its Id and web log Id /// Try to find a post by its Id and web log Id
let tryFindPost conn webLogId postId : Post option = let tryFindPost conn webLogId postId : Post option =
match r.Table(Table.Post) r.Table(Table.Post)
.Get(postId) .Get(postId)
.Filter(ReqlFunction1(fun p -> upcast p.["WebLogId"].Eq(webLogId))) .Filter(ReqlFunction1(fun p -> upcast p.["WebLogId"].Eq(webLogId)))
.RunAtomAsync<Post>(conn) .RunResultAsync<Post>(conn)
|> box with |> await
| null -> None |> box
| post -> Some <| unbox post |> function null -> None | post -> Some <| unbox post
/// Try to find a post by its permalink /// Try to find a post by its permalink
let tryFindPostByPermalink conn webLogId permalink = let tryFindPostByPermalink conn webLogId permalink =
r.Table(Table.Post) r.Table(Table.Post)
.GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink") .GetAll(r.Array(webLogId, permalink)).OptArg("index", "Permalink")
.Filter(fun p -> p.["Status"].Eq(PostStatus.Published)) .Filter(ReqlFunction1(fun p -> upcast p.["Status"].Eq(PostStatus.Published)))
.Without("Revisions") .Without("Revisions")
.Merge(fun p -> r.HashMap("Categories", r.Table(Table.Category) .Merge(ReqlFunction1(fun p ->
.GetAll(p.["CategoryIds"]) upcast r.HashMap("Categories", r.Table(Table.Category)
.Without("Children") .GetAll(p.["CategoryIds"])
.OrderBy("Name") .Without("Children")
.CoerceTo("array"))) .OrderBy("Name")
.Merge(fun p -> r.HashMap("Comments", r.Table(Table.Comment) .CoerceTo("array"))))
.GetAll(p.["Id"]).OptArg("index", "PostId") .Merge(ReqlFunction1(fun p ->
.OrderBy("PostedOn") upcast r.HashMap("Comments", r.Table(Table.Comment)
.CoerceTo("array"))) .GetAll(p.["id"]).OptArg("index", "PostId")
.RunCursorAsync<Post>(conn) .OrderBy("PostedOn")
.CoerceTo("array"))))
.RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead
/// Try to find a post by its prior permalink /// Try to find a post by its prior permalink
let tryFindPostByPriorPermalink conn (webLogId : string) (permalink : string) = let tryFindPostByPriorPermalink conn (webLogId : string) (permalink : string) =
r.Table(Table.Post) r.Table(Table.Post)
.GetAll(webLogId).OptArg("index", "WebLogId") .GetAll(webLogId).OptArg("index", "WebLogId")
.Filter(fun p -> p.["PriorPermalinks"].Contains(permalink).And(p.["Status"].Eq(PostStatus.Published))) .Filter(ReqlFunction1(fun p ->
upcast p.["PriorPermalinks"].Contains(permalink).And(p.["Status"].Eq(PostStatus.Published))))
.Without("Revisions") .Without("Revisions")
.RunCursorAsync<Post>(conn) .RunResultAsync<Post list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead
/// Get a set of posts for RSS /// Get a set of posts for RSS
let findFeedPosts conn webLogId nbr : (Post * User option) list = let findFeedPosts conn webLogId nbr : (Post * User option) list =
(publishedPosts webLogId) (publishedPosts webLogId)
.Merge(fun post -> r.HashMap("Categories", r.Table(Table.Category) .Merge(ReqlFunction1(fun post ->
.GetAll(post.["CategoryIds"]) upcast r.HashMap("Categories", r.Table(Table.Category)
.OrderBy("Name") .GetAll(post.["CategoryIds"])
.Pluck("Id", "Name") .OrderBy("Name")
.CoerceTo("array"))) .Pluck("id", "Name")
.CoerceTo("array"))))
|> toPostList conn 1 nbr |> toPostList conn 1 nbr
|> List.map (fun post -> post, match r.Table(Table.User) |> List.map (fun post -> post, r.Table(Table.User)
.Get(post.AuthorId) .Get(post.AuthorId)
.RunAtomAsync<User>(conn) .RunAtomAsync<User>(conn)
|> await |> await
|> box with |> box
| null -> None |> function null -> None | user -> Some <| unbox user)
| user -> Some <| unbox user)
/// Add a post /// Add a post
let addPost conn post = let addPost conn post =
r.Table(Table.Post) r.Table(Table.Post)
.Insert(post) .Insert(post)
.RunResultAsync(conn) .RunResultAsync(conn)
|> await
|> ignore |> ignore
/// Update a post /// Update a post
let updatePost conn post = let updatePost conn (post : Post) =
r.Table(Table.Post) r.Table(Table.Post)
.Get(post.Id) .Get(post.Id)
.Replace( { post with Categories = [] .Replace( { post with Categories = []
Comments = [] } ) Comments = [] } )
.RunResultAsync(conn) .RunResultAsync(conn)
|> await
|> ignore |> ignore
/// Save a post /// Save a post
let savePost conn post = let savePost conn (post : Post) =
match post.Id with match post.Id with
| "new" -> let newPost = { post with Id = string <| System.Guid.NewGuid() } | "new" -> let newPost = { post with Id = string <| System.Guid.NewGuid() }
r.Table(Table.Post) r.Table(Table.Post)
.Insert(newPost) .Insert(newPost)
.RunResultAsync(conn) .RunResultAsync(conn)
|> await
|> ignore |> ignore
newPost.Id newPost.Id
| _ -> r.Table(Table.Post) | _ -> r.Table(Table.Post)
@ -173,5 +177,6 @@ let savePost conn post =
.Replace( { post with Categories = [] .Replace( { post with Categories = []
Comments = [] } ) Comments = [] } )
.RunResultAsync(conn) .RunResultAsync(conn)
|> await
|> ignore |> ignore
post.Id post.Id

View File

@ -11,8 +11,8 @@ let private logStepDone () = Console.Out.WriteLine (" done.")
/// Ensure the myWebLog database exists /// Ensure the myWebLog database exists
let private checkDatabase (cfg : DataConfig) = let private checkDatabase (cfg : DataConfig) =
logStep "|> Checking database" logStep "|> Checking database"
let dbs = r.DbList().RunListAsync<string>(cfg.Conn) |> await let dbs = r.DbList().RunResultAsync<string list>(cfg.Conn) |> await
match dbs.Contains cfg.Database with match List.contains cfg.Database dbs with
| true -> () | true -> ()
| _ -> logStepStart (sprintf " %s database not found - creating" cfg.Database) | _ -> logStepStart (sprintf " %s database not found - creating" cfg.Database)
r.DbCreate(cfg.Database).RunResultAsync(cfg.Conn) |> await |> ignore r.DbCreate(cfg.Database).RunResultAsync(cfg.Conn) |> await |> ignore
@ -21,14 +21,12 @@ let private checkDatabase (cfg : DataConfig) =
/// Ensure all required tables exist /// Ensure all required tables exist
let private checkTables cfg = let private checkTables cfg =
logStep "|> Checking tables" logStep "|> Checking tables"
let tables = r.Db(cfg.Database).TableList().RunListAsync<string>(cfg.Conn) |> await let tables = r.Db(cfg.Database).TableList().RunResultAsync<string list>(cfg.Conn) |> await
[ Table.Category; Table.Comment; Table.Page; Table.Post; Table.User; Table.WebLog ] [ Table.Category; Table.Comment; Table.Page; Table.Post; Table.User; Table.WebLog ]
|> List.map (fun tbl -> match tables.Contains tbl with true -> None | _ -> Some (tbl, r.TableCreate tbl)) |> List.filter (fun tbl -> not (List.contains tbl tables))
|> List.filter Option.isSome |> List.iter (fun tbl -> logStepStart (sprintf " Creating table %s" tbl)
|> List.map Option.get (r.TableCreate tbl).RunResultAsync(cfg.Conn) |> await |> ignore
|> List.iter (fun (tbl, create) -> logStepStart (sprintf " Creating table %s" tbl) logStepDone ())
create.RunResultAsync(cfg.Conn) |> await |> ignore
logStepDone ())
/// Shorthand to get the table /// Shorthand to get the table
let private tbl cfg table = r.Db(cfg.Database).Table(table) let private tbl cfg table = r.Db(cfg.Database).Table(table)
@ -42,15 +40,15 @@ let private createIndex cfg table (index : string * (ReqlExpr -> obj) option) =
| None -> (tbl cfg table).IndexCreate(idxName)) | None -> (tbl cfg table).IndexCreate(idxName))
.RunResultAsync(cfg.Conn) .RunResultAsync(cfg.Conn)
|> await |> ignore |> await |> ignore
(tbl cfg table).IndexWait(idxName).RunAtomAsync(cfg.Conn) |> await |> ignore (tbl cfg table).IndexWait(idxName).RunResultAsync(cfg.Conn) |> await |> ignore
logStepDone () logStepDone ()
/// Ensure that the given indexes exist, and create them if required /// Ensure that the given indexes exist, and create them if required
let private ensureIndexes cfg (indexes : (string * (string * (ReqlExpr -> obj) option) list) list) = let private ensureIndexes cfg (indexes : (string * (string * (ReqlExpr -> obj) option) list) list) =
let ensureForTable (tblName, idxs) = let ensureForTable (tblName, idxs) =
let idx = (tbl cfg tblName).IndexList().RunListAsync<string>(cfg.Conn) |> await let idx = (tbl cfg tblName).IndexList().RunResultAsync<string list>(cfg.Conn) |> await
idxs idxs
|> List.iter (fun index -> match idx.Contains (fst index) with true -> () | _ -> createIndex cfg tblName index) |> List.iter (fun index -> match List.contains (fst index) idx with true -> () | _ -> createIndex cfg tblName index)
indexes indexes
|> List.iter ensureForTable |> List.iter ensureForTable

View File

@ -1,6 +1,7 @@
module MyWebLog.Data.RethinkDB.User module MyWebLog.Data.RethinkDB.User
open MyWebLog.Entities open MyWebLog.Entities
open RethinkDb.Driver.Ast
let private r = RethinkDb.Driver.RethinkDB.R let private r = RethinkDb.Driver.RethinkDB.R
@ -11,7 +12,7 @@ let private r = RethinkDb.Driver.RethinkDB.R
let tryUserLogOn conn (email : string) (passwordHash : string) = let tryUserLogOn conn (email : string) (passwordHash : string) =
r.Table(Table.User) r.Table(Table.User)
.GetAll(email).OptArg("index", "UserName") .GetAll(email).OptArg("index", "UserName")
.Filter(fun u -> u.["PasswordHash"].Eq(passwordHash)) .Filter(ReqlFunction1(fun u -> upcast u.["PasswordHash"].Eq(passwordHash)))
.RunCursorAsync<User>(conn) .RunResultAsync<User list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead

View File

@ -9,21 +9,22 @@ let private r = RethinkDb.Driver.RethinkDB.R
let tryFindWebLogByUrlBase conn (urlBase : string) = let tryFindWebLogByUrlBase conn (urlBase : string) =
r.Table(Table.WebLog) r.Table(Table.WebLog)
.GetAll(urlBase).OptArg("index", "UrlBase") .GetAll(urlBase).OptArg("index", "UrlBase")
.Merge(fun w -> r.HashMap("PageList", r.Table(Table.Page) .Merge(ReqlFunction1(fun w ->
.GetAll(w.["Id"]).OptArg("index", "WebLogId") upcast r.HashMap("PageList", r.Table(Table.Page)
.Filter(ReqlFunction1(fun pg -> upcast pg.["ShowInPageList"].Eq(true))) .GetAll(w.G("id")).OptArg("index", "WebLogId")
.OrderBy("Title") .Filter(ReqlFunction1(fun pg -> upcast pg.["ShowInPageList"].Eq(true)))
.Pluck("Title", "Permalink") .OrderBy("Title")
.CoerceTo("array"))) .Pluck("Title", "Permalink")
.RunCursorAsync<WebLog>(conn) .CoerceTo("array"))))
.RunResultAsync<WebLog list>(conn)
|> await |> await
|> Seq.tryHead |> List.tryHead
/// Get counts for the admin dashboard /// Get counts for the admin dashboard
let findDashboardCounts conn (webLogId : string) = let findDashboardCounts conn (webLogId : string) =
r.Expr( r.HashMap("Pages", r.Table(Table.Page ).GetAll(webLogId).OptArg("index", "WebLogId").Count())) r.Expr( r.HashMap("Pages", r.Table(Table.Page ).GetAll(webLogId).OptArg("index", "WebLogId").Count()))
.Merge(r.HashMap("Posts", r.Table(Table.Post ).GetAll(webLogId).OptArg("index", "WebLogId").Count())) .Merge(r.HashMap("Posts", r.Table(Table.Post ).GetAll(webLogId).OptArg("index", "WebLogId").Count()))
.Merge(r.HashMap("Categories", r.Table(Table.Category).GetAll(webLogId).OptArg("index", "WebLogId").Count())) .Merge(r.HashMap("Categories", r.Table(Table.Category).GetAll(webLogId).OptArg("index", "WebLogId").Count()))
.RunAtomAsync<DashboardCounts>(conn) .RunResultAsync<DashboardCounts>(conn)
|> await |> await

View File

@ -1,4 +1,4 @@
namespace myWebLog.Data.AssemblyInfo namespace MyWebLog.Entities.AssemblyInfo
open System.Reflection open System.Reflection
open System.Runtime.CompilerServices open System.Runtime.CompilerServices

View File

@ -51,7 +51,7 @@ let tryFindPostByPriorPermalink (data : IMyWebLogData) webLogId permalink = data
let findFeedPosts (data : IMyWebLogData) webLogId nbrOfPosts = data.FeedPosts webLogId nbrOfPosts let findFeedPosts (data : IMyWebLogData) webLogId nbrOfPosts = data.FeedPosts webLogId nbrOfPosts
/// Save a post /// Save a post
let savePost (data : IMyWebLogData) post = let savePost (data : IMyWebLogData) (post : Post) =
match post.Id with match post.Id with
| "new" -> let newPost = { post with Id = string <| System.Guid.NewGuid() } | "new" -> let newPost = { post with Id = string <| System.Guid.NewGuid() }
data.AddPost newPost data.AddPost newPost