diff --git a/notebooks/CRUD-Guide.ipynb b/notebooks/CRUD-Guide.ipynb index 0673645..2dac03e 100644 --- a/notebooks/CRUD-Guide.ipynb +++ b/notebooks/CRUD-Guide.ipynb @@ -1,12 +1,5 @@ { "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/src/Mondocks/Aggregation.fs b/src/Mondocks/Aggregation.fs index 825b74b..56fc8d3 100644 --- a/src/Mondocks/Aggregation.fs +++ b/src/Mondocks/Aggregation.fs @@ -8,6 +8,11 @@ module Aggregation = [] module Count = + + /// + /// Represents a `Count` command + /// for more information take a look at count syntax + /// type CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment> = { count: string query: Option<'TDocument> @@ -36,18 +41,61 @@ module Aggregation = member __.Run(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>) = (state :> IBuilder).ToJSON() + ///The name of the collection to query against + /// + /// count { + /// collection "users" + /// query {| age = 50 |} + /// } + /// [] member __.Count(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>, count: string) = { state with count = count } + /// + /// Optional object that is going to be used to filter the find query + /// + /// + /// count { + /// collection "users" + /// // counts all the users with the name "Frank" + /// query {| name = "Frank"|} + /// } + /// [] member __.Query(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>, query: 'TDocument) = { state with query = Some query } + /// + /// Optional. An integer value used to omit the first n amount of documents from the find query + /// Use together with Limit to paginate results + /// + /// + /// count { + /// collection "users" + /// // ... omit other fields + /// // omits the first 10 results of the count query + /// skip 10 + /// // ... omit other fields + /// } + /// [] member __.Limit(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>, limit: int) = { state with limit = Some limit } + /// + /// Optional. An integer value used to take at most n amount of documents + /// Use together with Skip to paginate results + /// + /// + /// count { + /// collection "users" + /// // ... omit other fields + /// // takes only 10 documents from the count query + /// limit 10 + /// // ... omit other fields + /// } + /// [] member __.Skip(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>, skip: int) = { state with skip = Some skip } @@ -65,11 +113,19 @@ module Aggregation = member __.Comment(state: CountCommand<'TDocument, 'Hint, 'ReadConcern, 'Comment>, comment: 'Comment) = { state with comment = Some comment } + /// Creates an count command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a CountCommandBuilder let count = CountCommandBuilder() [] module Distinct = + + /// + /// Represents a `Distinct` command + /// for more information take a look at count syntax + /// type DistinctCommand<'TDocument, 'ReadConcern, 'Comment> = { distinct: string key: string @@ -95,10 +151,28 @@ module Aggregation = ({ state with distinct = collection } :> IBuilder) .ToJSON() + /// + /// A key used to retreive values from the query result documents + /// + /// + /// distinct "users" { + /// key "email" + /// } + /// [] member __.Key(state: DistinctCommand<'TDocument, 'ReadConcern, 'Comment>, key: string) = { state with key = key } + /// + /// Optional. A filter to query against the collection + /// + /// + /// distinct "users" { + /// // gets all of the distinc emails from users named "Frank" + /// key "email" + /// query {| name = "Frank"|} + /// } + /// [] member __.Query(state: DistinctCommand<'TDocument, 'ReadConcern, 'Comment>, query: 'TDocument) = { state with query = Some query } @@ -117,4 +191,7 @@ module Aggregation = member __.Comment(state: DistinctCommand<'TDocument, 'ReadConcern, 'Comment>, comment: 'Comment) = { state with comment = Some comment } + /// Creates an update command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a DistinctCommandBuilder let distinct (collection: string) = DistinctCommandBuilder(collection) diff --git a/src/Mondocks/Mondocks.fsproj b/src/Mondocks/Mondocks.fsproj index 6a28f2e..3d1f6a7 100644 --- a/src/Mondocks/Mondocks.fsproj +++ b/src/Mondocks/Mondocks.fsproj @@ -5,6 +5,7 @@ net5.0;netstandard2.0 true true + true diff --git a/src/Mondocks/Query.fs b/src/Mondocks/Query.fs index 8303c89..7016aa1 100644 --- a/src/Mondocks/Query.fs +++ b/src/Mondocks/Query.fs @@ -6,13 +6,32 @@ module Queries = [] module Find = + /// + /// Represents a Find command + /// for more information take a look at find syntax + /// type FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min> = - { find: string + { + /// Name of the collection where this find operation will be targeted + find: string + /// Optional object that is going to be used to filter filter: Option<'Filter> + /// + /// optional object to sort by property + /// + /// + /// Some {| ``$sort`` = {| name = 1; age = -1 |} |} + /// + /// + /// None + /// sort: Option<'Sort> + /// A projection object projection: Option<'Projection> hint: Option<'Hint> + /// User for pagination skip: Option + /// User for pagination limit: Option batchSize: Option singleBatch: Option @@ -34,14 +53,50 @@ module Queries = interface IBuilder with member __.ToJSON() = Json.Serialize __ + /// + /// Tries to find a single document and apply the supplied modifications to it + /// Reference + /// type FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment> = - { findAndModify: string + { /// name of the collection where this query is targeted at + findAndModify: string + /// An optional object that will be used as a filter for the query query: Option<'Query> + /// + /// optional object to sort by property + /// + /// + /// Some {| ``$sort`` = {| name = 1; age = -1 |} |} + /// + /// + /// None + /// sort: Option<'Sort> + /// Optional property that indicates whether this document should be removed or not. + /// Must specify either the remove or the update field remove: Option + /// Optional property that indicates the new values for the objects that match the query. + /// Must specify either the remove or the update field update: Option<'Update> + /// optional + /// When true, returns the modified document rather than the original ``new``: Option + /// + /// A subset of fields to return. The fields document specifies an inclusion of a field with 1, as in + /// + /// + /// Some {| name = 1; password = 0 |} + /// + /// + /// None + /// fields: Option<'Fields> + /// + /// Optional. + /// Used in conjunction with the update field. + /// Creates a new document if no documents match the query + /// Updates a single document that matches the query. + /// upsert: Option bypassDocumentValidation: Option writeConcern: Option<'WriteConcern> @@ -79,19 +134,55 @@ module Queries = collation = None allowDiskUse = None } - member __.Run(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>) = - ({ state with find = collection } :> IBuilder).ToJSON() + /// + /// Converts the query into a serialized string + /// + member __.Run(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>) = + ({ state with find = collection } :> IBuilder) + .ToJSON() + + /// + /// Optional object that is going to be used to filter the find query + /// + /// + /// find "user" { + /// // filters by name equals Frank + /// filter {| name = "Frank"|} + /// } + /// [] member __.WithFilter(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>, filter: 'Filter) = { state with filter = Some filter } + /// + /// Optional. Object to sort by property + /// + /// + /// find "user" { + /// // ... omit other fields + /// // sorts by name ascending and age descending + /// sort {| ``$sort`` = {| name = 1; age = -1 |} |} + /// // ... omit other fields + /// } + /// [] member __.WithSort(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>, sort: 'Sort) = { state with sort = Some sort } + /// + /// A Projection Object + /// + /// + /// find "user" { + /// // ... omit other fields + /// // from the found documents bring only the name and the age, omit the password + /// projection {| name = 1; age = 1; password = 0 |} + /// // ... omit other fields + /// } + /// [] member __.WithProjection(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>, projection: 'Projection) = @@ -103,11 +194,35 @@ module Queries = hint: 'Hint) = { state with hint = Some hint } + /// + /// Optional. An integer value used to omit the first n amount of documents from the find query + /// Use together with Limit to paginate results + /// + /// + /// find "user" { + /// // ... omit other fields + /// // omits the first 10 results of the find query + /// skip 10 + /// // ... omit other fields + /// } + /// [] member __.WithSkip(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>, skip: int) = { state with skip = Some skip } + /// + /// Optional. An integer value used to take at most n amount of documents + /// Use together with Skip to paginate results + /// + /// + /// find "user" { + /// // ... omit other fields + /// // takes only 10 documents from the find query + /// limit 10 + /// // ... omit other fields + /// } + /// [] member __.WithLimit(state: FindCommand<'Filter, 'Sort, 'Projection, 'Hint, 'Comment, 'ReadConcern, 'Max, 'Min>, limit: int) = @@ -224,26 +339,61 @@ module Queries = hint = None comment = None } + /// + /// Converts the query into a serialized string + /// member __.Run(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>) = ({ state with - findAndModify = collection } :> IBuilder).ToJSON() - + findAndModify = collection } + :> IBuilder) + .ToJSON() + + /// + /// Optional object that is going to be used to filter the findAndModify query + /// + /// + /// findAndModify "user" { + /// // filters the collection for names that are either + /// // Frank, Sandra, Peter or Monica + /// query {| name = {| ``$in`` = ["Frank"; "Sandra"; "Peter"; "Monica"] |} + /// } + /// + /// + /// findAndModify "user" { + /// // filters by age where the age is greater or equal than 30 + /// query {| age = {| ``$gte`` = 30 |} + /// } + /// [] member __.WithQuery(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, query: 'Query) = { state with query = Some query } + + /// + /// A Projection Object + /// + /// + /// findAndModify "user" { + /// // ... omit other fields + /// // sorts by name ascending and age descending + /// sort {| ``$sort`` = {| name = 1; age = -1 |} |} + /// // ... omit other fields + /// } + /// [] member __.WithSort(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, sort: 'Sort) = { state with sort = Some sort } - + /// Optional. property that indicates whether this document should be removed or not. + /// Must specify either the remove or the update field [] member __.WithRemove(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, remove: bool) = { state with remove = Some remove } - + /// Optional. property that indicates the new values for the objects that match the query. + /// Must specify either the remove or the update field [] member __.WithUpdate(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, update: 'Update) = @@ -254,11 +404,29 @@ module Queries = withNew: bool) = { state with ``new`` = Some withNew } + /// + /// A Projection Object. + /// It is a subset of fields to return. The fields document specifies an inclusion of a field with 1 + /// + /// + /// findAndModify "user" { + /// // ... omit other fields + /// // from the found documents bring only the name and the age, omit the password + /// fields {| name = 1; age = 1; password = 0 |} + /// // ... omit other fields + /// } + /// [] member __.WithFields(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, fields: 'Fields) = { state with fields = Some fields } + /// + /// Optional. + /// Used in conjunction with the update field. + /// Creates a new document if no documents match the query + /// Updates a single document that matches the query. + /// [] member __.WithUpsert(state: FindAndModifyCommand<'Query, 'Sort, 'Update, 'Fields, 'WriteConcern, 'Hint, 'Comment>, upsert: bool) = @@ -299,8 +467,14 @@ module Queries = comment: 'Comment) = { state with comment = Some comment } - + /// creates a find and modify command for a single document + /// The name of the collection to perform this query against + /// returns a FindAndModifyBuilder let findAndModify (collection: string) = FindAndModifyBuilder(collection) + + /// Creates a find command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a FindBuilder let find (collection: string) = FindBuilder(collection) [] @@ -323,14 +497,45 @@ module Queries = writeConcern = None } member __.Run(state: DeleteCommand<'WriteConcern>) = - ({ state with delete = collection } :> IBuilder).ToJSON() - - + ({ state with delete = collection } :> IBuilder) + .ToJSON() + + /// + /// A sequence of anonymous record objects (boxed) that will be used + /// to perform against the collection + /// + /// + /// delete "users" { + /// // deletes 1 user named "Peter" + /// deletes [box {| q = {| name = "Peter" |}; limit = 1 |}] + /// } + /// [] - member __.WithDeletes(state: DeleteCommand<'WriteConcern>, - deletes: seq>) = - { state with - deletes = deletes |> Seq.map box } + member __.WithDeletes(state: DeleteCommand<'WriteConcern>, deletes: seq) = + { state with deletes = deletes } + + /// + /// A sequence of DeleteQuery objects that will be used + /// to perform against the collection + /// + /// + /// delete "users" { + /// // filters the collection for names that are either + /// // Frank, Sandra, Peter or Monica + /// deletes [ + /// { q = {| name = name |} + /// // To delete all documents that match + /// // `limit = 0` + /// limit = 1 + /// collation = None + /// hint = None + /// comment = None } + /// ] + /// } + /// + member this.WithDeletes(state: DeleteCommand<'WriteConcern>, + deletes: seq>) = + this.WithDeletes(state, deletes |> Seq.map box) [] member __.WithOrdered(state: DeleteCommand<'WriteConcern>, ordered: bool) = @@ -341,6 +546,9 @@ module Queries = { state with writeConcern = Some concern } + /// Creates a delete command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a DeleteBuilder let delete (collection: string) = DeleteBuilder(collection) @@ -368,9 +576,30 @@ module Queries = comment = None } member __.Run(state: InsertCommand<'TDocument, 'WriteConcern, 'Comment>) = - ({ state with insert = collection } :> IBuilder).ToJSON() - - + ({ state with insert = collection } :> IBuilder) + .ToJSON() + + /// + /// A sequence of documents that will be inserted + /// into the collection, they can be records or anonymous records + /// + /// + /// type Post = { title: string; content: string } + /// insert "posts" { + /// // Inserts two new documents + /// documents + /// [ { title= "Title"; content = "Content" } + /// { title= "Title"; content = "Content" } ] + /// } + /// + /// + /// insert "posts" { + /// // Inserts two new documents + /// documents + /// [ {| title= "Title"; content = "Content" |} + /// {| title= "Title"; content = "Content" |} ] + /// } + /// [] member __.WithDocuments(state: InsertCommand<'TDocument, 'WriteConcern, 'Comment>, documents: seq<'TDocument>) = @@ -396,6 +625,9 @@ module Queries = member __.WithComment(state: InsertCommand<'TDocument, 'WriteConcern, 'Comment>, comment: 'Comment) = { state with comment = Some comment } + /// Creates an insert command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a InserCommandBuilder let insert (collection: string) = InsertCommandBuilder(collection) [] @@ -422,14 +654,46 @@ module Queries = comment = None } member __.Run(state: UpdateCommand<'WriteConcern, 'Comment>) = - ({ state with update = collection } :> IBuilder).ToJSON() - - + ({ state with update = collection } :> IBuilder) + .ToJSON() + + + /// + /// A sequence of custom documents that will be used to query against the collection + /// + /// + /// update "users" { + /// // Inserts two new documents + /// updates + /// [ box {| q = {| _id = user._id |} + /// u = {| user with email = "new@email.com" |} + /// upsert = true + /// multi = false |} ] + /// } + /// [] - member __.WithUpdates(state: UpdateCommand<'WriteConcern, 'Comment>, - updates: seq>) = - { state with - updates = updates |> Seq.map box } + member __.WithUpdates(state: UpdateCommand<'WriteConcern, 'Comment>, updates: seq) = + { state with updates = updates } + + /// + /// A sequence of custom documents that will be used to query against the collection + /// + /// + /// update "users" { + /// // Inserts two new documents + /// updates + /// [ { q = {| _id = user._id |} + /// u = { user with email = "new@email.com" } + /// upsert = Some false + /// multi = Some false + /// collation = None + /// arrayFilters = None + /// hint = None } ] + /// } + /// + member this.WithUpdates(state: UpdateCommand<'WriteConcern, 'Comment>, + updates: seq>) = + this.WithUpdates(state, updates |> Seq.map box) [] member __.WithOrdered(state: UpdateCommand<'WriteConcern, 'Comment>, ordered: bool) = @@ -450,4 +714,7 @@ module Queries = member __.WithComment(state: UpdateCommand<'WriteConcern, 'Comment>, comment: 'Comment) = { state with comment = Some comment } + /// Creates an update command for documents in the specified collection + /// The name of the collection to perform this query against + /// returns a UpdateCommandBuilder let update (collection: string) = UpdateCommandBuilder(collection)