Use $stdDevSamp or $stdDevPop with Spring Mongo

2019-08-09 15:03发布

I'd like to know how to implement a Standard Deviation aggregation Function to use in Spring Mongo Data.

I Know Mongo DB 3.2 has a Standard Deviation aggregation function, but It isn't available in Spring Data.

Could I use the Mongo's aggregation function?

Thanks.

1条回答
来,给爷笑一个
2楼-- · 2019-08-09 15:17

There is a distinct difference between "not available" and "no implemented helper method", and that is the real case here. Just because there is no "helper" for implementing the $stdDevSamp or $stdDevPop operators, does not mean they cannot be used, as long as you are connecting to a MongoDB 3.2 instance of course.

All you really need is a custom class supporting the AggregationOperation interface, that will allow construction using DBObject:

public class CustomAggregationOperation implements AggregationOperation {
    private DBObject operation;

    public CustomAggregationOperation (DBObject operation) {
        this.operation = operation;
    }

    @Override
    public DBObject toDBObject(AggregationOperationContext context) {
        return context.getMappedObject(operation);
    }
}

Then you can use that class in aggregation pipeline construction like so:

Aggregation aggregation = newAggregation(
    new CustomAggregationOperation(
        new BasicDBObject("$sample", new BasicDBObject("size",100))
    ),
    new CustomAggregationOperation(
        new BasicDBObject(
            "$group",
            new BasicDBObject("_id",null)
                .append("ageStdDev",new BasicDBObject("$stdDevSamp","$age"))
        )
    )
);

And that is the equivalent of the documentation example:

db.users.aggregate(
   [
      { "$sample": { "size": 100 } },
      { "$group": { "_id": null, "ageStdDev": { "$stdDevSamp": "$age" } } }
   ]
)

As an interface for AggregationOperation the class easily mixes with the implemented helpers:

Aggregation aggregation = newAggregation(
    // Using the match helper for the `$match` stage
    match(
        Criteria.where("age").gte(20).lte(50)
    ),
    // Mixed in with custom classes for the others
    new CustomAggregationOperation(
        new BasicDBObject("$sample", new BasicDBObject("size",100))
    ),
    new CustomAggregationOperation(
        new BasicDBObject(
            "$group",
            new BasicDBObject("_id",null)
                .append("ageStdDev",new BasicDBObject("$stdDevSamp","$age"))
        )
    )
);

So you can still use features even if there is no "buit in helper" to work out the BSON Object construction for you. You just do the construction yourself.

查看更多
登录 后发表回答