thedodd/wither

How to run aggregations?

Opened this issue · 3 comments

What is the intended method to run an aggregation query with wither?

Currently I am doing something like this:

let path_regex = wither::bson::Regex { pattern: format!("{}.*", path), options: String::new() };
let pipeline = vec!
    [
        doc!{
            "$match": {
                "path": path_regex
            }
        },
        doc!{
            "$sample": {
                "size": 1
            }
        }
    ];

let mut cursor: Cursor<_> = DataBlockMongo::collection(&db).aggregate(pipeline, AggregateOptions::default()).await.unwrap();

if let Some(chosen_item) = cursor.next().await {
    let chosen_item = DataBlockMongo::instance_from_document(chosen_item.unwrap()).unwrap();
}

Which works, but requires converting to and from a document.

Is this the intended method?
If so, I can't seem to find this documented anywhere.

@8176135 currently that is the only way to do so, and that is part of the reason I decided to expose the instance_from_document method on Model impls.

I think it shouldn't be a heavy lift at all to encapsulate this behavior that you've shown above. Technically there are plenty of things which a user can do to cause the output of an agg pipeline to break serialization ... so perhaps we introduce a new Model::aggregate method, and then simply include in the docs that the output is expected to be able to deserialize as model instances.

If the output is not intended to deserialize as model instances, then perhaps we recommend using the collection's aggregate method. What do you think?

I am particularily interested in the $lookup operator since I have some simple relations that currently I handle with the instance_from_document.

Is this still planned?
I have a version of wither sitting on my fork right now that supports Model::aggregate.
My fork, however, requires mongodb version 2.21.