EnhancingtheF # unzip experiencewithmongodb

Source: Internet
Author: User
ThisisaguestpostbyMaxHirschhorn, whoiscurrentlyaninternatMongoDB. AbouttheF # programminglanguageF # isamulti-paradigmlanguagebuiltonthe.NETframework.Itisfunctional-firstandprefersimmutability, butalsosupportso

This is a guest post by Max Hirschhorn, who is currently an intern at MongoDB. about the F # programming language F # is a multi-paradigm language built on. NET framework. it isfunctional-first and prefers immutability, but also supportso

This is a guest post by Max Hirschhorn, who is currently an intern at MongoDB.

About the F # programming language

F # is a multi-paradigm language built on the. NET framework. It isfunctional-first and prefers immutability, but also supportsobject-oriented and imperative programming styles.

Also, F # is a statically-typed language with a type inference system. It has a syntax similar to Ocaml, and draws upon ideas from otherfunctional programming versions such as Erlang and Haskell.

Using the existing. NET driver

The existing. NET driver is compatible with F #, but is not necessarilywritten in a way that is idiomatic to use from F #.

Part of the reason behind this is thatEverythingIn F # is explicit. For example, consider the following example interface and implementingclass.

[]type I =    abstract Foo : unit -> stringtype C() =    interface I with        member __.Foo () = "bar"// example usagelet c = C()(c :> I).Foo()

So in order to use any of the interface members, the class must beupcasted usingthe:>Operator. Note that this cast is still checked at compile-time.

In a similar vein, C # supports implicitoperators, which the BSON library uses for converting between a primitive valueand itsBsonValueEquivalent, e.g.

new BsonDocument {    { "price", 1.99 },    { "$or", new BsonDocument {        { "qty", new BsonDocument { { "$lt", 20 } } },        { "sale", true }    } }};

Whereas F # does not. This requires the developer to explicitlyconstruct the appropriate typeBsonValue, E.g.

BsonDocument([ BsonElement("price", BsonDouble(1.99))               BsonElement("$or", BsonArray([ BsonDocument("qty", BsonDocument("$lt", BsonInt32(20)))                                              BsonDocument("sale", BsonBoolean(true)) ])) ])

With the query builder, we can hide the constructionBsonDocumentInstances, e.g.

Query.And([ Query.EQ("price", BsonDouble(1.99))            Query.OR([ Query.LT("qty", BsonInt32(20))                       Query.EQ("sale", BsonBoolean(true)) ]) ])

It is worth noting that the need to constructBsonValueInstancesis completely avoided when using a typedQueryBuilder.

type Item = {    Price : float    Quantity : int    Sale : bool}let query = QueryBuilder()query.And([ query.EQ((fun item -> item.Price), 1.99)            query.Or([ query.LT((fun item -> item.Quantity), 20)                       query.EQ((fun item -> item.Sale), true) ]) ])

What we are looking for is a solution that matches the breech of F # code, offers type-safety if desired, and is easy to use from thelanguage.

New features

The main focus of this project is to make writing queries againstMongoDB as natural from the F # language as possible.

bsonQuotations

We strive to make writing predicates as natural as possible by reusingas equal of the existing operators as possible.

A taste

Consider the following query

{ price: 1.99, $or: [ { qty: { $lt: 20 } }, { sale: true } ] }

We cocould express this with a codequotation

bson <@ fun (x : BsonDocument) -> x?price = 1.99 && (x?qty < 20 || x?sale = true) @>

Or with type safety

bson <@ fun (x : Item) -> x.Price = 1.99 && (x.Quantity < 20 || x.Sale = true) @>
Breaking it down

The quotations areNotActually executed, but instead are presentedas an abstract syntax tree (AST), from which an equivalentBsonDocumentInstance is constructed.

The ?Operator

The?Operator is defined to allow for an unchecked comparison. TheF # language supports the ability to do a dynamic lookup (get) andassignment (set) via?And?<-Operators respectively, but doesnot actually provide a implementation.

So, the F # driver defines?Operator as the value associated witha field in a document casted to a fresh generic type.

// type signature: BsonDocument -> string -> 'alet (?) (doc : BsonDocument) (field : string) =    unbox doc.[field]

And similarly defines?<-Operator as the coerced assignment of agenerically typed value to the associated field in the document.

// type signature: BsonDocument -> string -> 'a -> unitlet (?<-) (doc : BsonDocument) (field : string) value =    doc.[field] = unbox value |> ignore
Queries

Unchecked expressions have the type signatureExpr bool> .

// $modbson <@ fun (x : BsonDocument) -> x?qty % 4 = 0 @>

Checked expressions have the type signatureExpr<'DocType -> bool>.

// $modbson <@ fun (x : Item) -> x.Quantity % 4 = 0 @>
Updates

Unchecked expressions have the type signatureExpr unit list> . The reason forlistIn thereturn type is to perform multiple update operations.

// $setbson <@ fun (x : BsonDocument) -> [ x?qty <- 20 ] @>// $incbson <@ fun (x : BsonDocument) -> [ x?qty <- (+) 1 ] @>
Mmm... Sugar

A keen observer wocould notice that(+) 1Is notint, But actuallya functionint -> int. We are abusing the fact that type safety isnot enforced here by assigning the quantity field of the document to alambda expression, that takes a single parameter of the current value.

Note that

// $incbson <@ fun (x : BsonDocument) -> [ x?qty <- x?qty + 1 ] @>

Is also valid.

Checked expressions either have the type signatureExpr<'DocType -> unit list>OrExpr<'DocType -> 'DocType>, Depending on whether the document type has mutable fields (only mattersfor record types ).

// $setbson <@ fun (x : Item) -> [ x.Quantity <- 20 ] @>// $incbson <@ fun (x : Item) -> [ x.Quantity <- x.Quantity + 1 ] @>
mongoExpressions

Uses the monadic structure (computation expression) to define a pipeline of operations that are executed on each using Entin the collection.

Queries
let collection : IMongoCollection = ...mongo {    for x in collection do    where (x?price = 1.99 && (x?qty < 20 || x?sale = true))}

Or with a typed collection

let collection : IMongoCollection = ...mongo {    for x in collection do    where (x.price = 1.99 && (x.qty < 20 || x.sale = true))}
Updates
let collection : IMongoCollection = ...mongo {    for x in collection do    update    set x?price 0.99    inc x?qty 1}

Or with a typed collection

let collection : IMongoCollection = ...mongo {    for x in collection do    update    set x.Price 0.99    inc x.Quantity 1}
Serialization of F # data types

Now supports

  • Record types
  • Option types
  • Discriminated unions
ConclusionResources

The source code is available atGitHub. We absolutely encourage you to experiment with it and provide usfeedback on the API, design, and implementation. Bug reports provided for improvements are welcomed, as are pull requests.

Disclause. The API and implementation are currently subject tochange at any time. YouMust notUse this driver in production, asit is still under development and is in no way supported by MongoDB, Inc.

Acknowledgments

Export thanks to the guidance from the F # community on Twitter, and mymentors: Sridhar Nanjundeswaran, Craig Wilson, and Robert Stam. also, a special thanks to Stacy Ferranti and Ian Whalen for overseeing theinternship program.

Original article address: Enhancing the F # developer experience with MongoDB. Thank you for sharing it with me.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.