Search code examples
.netmongodbf#mongodb-querymongodb.driver

Projecting results from MongoDb Find in F#


I'm trying to query MongoDB using MongoDB.Driver and return a partial result using mongo projection.

I've figured out how to query without projection, but not a partial result. This is my function for finding results:

let Find<'a> collectionName (filterDefinition: FilterDefinition<'a>) =
    let collection = database.GetCollection<'a> collectionName
    collection.Find(filterDefinition).ToEnumerable() |> List.ofSeq

This is an example of how I call it:

let findByIdFilter id =
    Builders<MyModel>.Filter.Eq((fun s -> s.id), id)

let results = Find collectionName (findByIdFilter id)

Let's say my model is something like that:

type MyInnerModel = {
    zInner: bool
}

type MyModel = {
    id: ObjectId
    x: int
    y: double
    z: MyInnerModel
}

And these are my projections:

type MyModelProjection1 = {
    id: ObjectId
    y: double
}

type MyModelProjection1 = {
    id: ObjectId
    x: int
    z: MyInnerModel
}

How do I construct my queries for following scenarios:

  • Find documents matching (fun (m: MyModel) -> m.z.zInner = false) with projection to MyModelProjection1
  • Find documents matching (fun (m: MyModel) -> m.x = 5) with projection to MyModelProjection2
  • Find ALL documents with projection to MyModelProjection1 or MyModelProjection2

Solution

  • You can define your projections like so:

    let projection1 =
        Builders<MyModel>.Projection.Expression(fun model ->
            { id = model.id; y = model.y })
    
    let projection2 =
        Builders<MyModel>.Projection.Expression(fun model ->
            { id = model.id; x = model.x; z = model.z })
    

    You can then use them in the following way:

        let one =
            collection
                .Find(fun m -> m.z.zInner = false)
                .Project(projection1).ToEnumerable() |> List.ofSeq
    
        let two =
            collection
                .Find(fun m -> m.x = 5)
                .Project(projection2).ToEnumerable() |> List.ofSeq
    
        let three =
            collection
                .Find(fun _ -> true)
                .Project(projection1).ToEnumerable() |> List.ofSeq
    
        let four =
            collection
                .Find(fun _ -> true)
                .Project(projection1).ToEnumerable() |> List.ofSeq