如何对mongodb查询的结果进行分组并在Java中实现?

时间:2016-03-03 18:54:01

标签: java mongodb

我在Mongo数据库中有一个如下所示的集合:

{
    "_id" : ObjectId("561b42d4e4b0d4227d011d2c"),
    "product_related_data" : {
        "depth" : 6,
        "height" : 23,
        "product_barcode" : "54491472",
        "product_name" : "xyz product",
        "product_uuid" : "009b9846-b3ad-49f7-a7a0-d35a04f83480",
        "width" : 6
    },
    "sensostrip_data" : {
        "barcode" : "130150208299",
        "battery_level" : 2.894
    },
    "stock_related_data" : {
        "calculated_max_product_percentage" : 15.625,
        "calculated_min_product_percentage" : 12.5,
        "current_stock" : 2,
        "max_stock" : 6,
        "stock_difference_percentage" : 0,
        "stock_difference_value" : 0,
        "stock_percentage" : 37.5
    },
    "store_data" : {
        "city_uuid" : "cbb4dfe8-172b-11e4-a1f0-00163ed23ec2",
        "ip" : "10.0.1.1",
        "retailer_uuid" : "8c33c32c-5903-11e4-a1f0-00163ed23ec2",
        "store_name" : "xyz store",
        "store_uuid" : "15a6cc90-081f-11e5-b213-001e6745ff8d"
    },
    "time" : {
        "check_date" : "2015-10-11 11:53:55",
        "previous_check_date" : "2015-10-11 11:48:57"
    },
    "id" : "6be54bef-0aa3-456c-b912-1731f8154e7d"
}

我正在执行的mongo查询返回 store_uuid 列表的所有文档以及 product_uuid 的所有文档,如下所示:

db.readings
.find({ $and:[ {"store_data.store_uuid": {$in:["15a6cc90-081f-11e5-b213-001e6745ff8d","217b983b-5904-11e4-a1f0-00163ed23ec2","5337d78d-5904-11e4-a1f0-00163ed23ec2"]}}
,{"product_related_data.product_uuid": "f44aa29d-09ce-4902-bf12-d45d44b3dfd0"}]})

我目前的 Java实现(我使用投影的地方)看起来像这样:

DBCollection table = databaseConncetion().getCollection("readings");

BasicDBObject sensorReturn = new BasicDBObject("sensostrip_data.barcode",1);

BasicDBObject clause1 = new BasicDBObject("store_data.store_uuid", new BasicDBObject("$in", StoreIds));

BasicDBObject clause2 = new BasicDBObject("product_related_data.product_uuid", productId);

BasicDBList and = new BasicDBList();
and.add(clause1);
and.add(clause2);

DBObject query = new BasicDBObject("$and", and);

DBCursor cursor = table.find(query, sensorReturn
        .append("stock_related_data.stock_percentage",1)
        .append("store_data.store_uuid",1)
        .append("time.check_date", 1))
        .sort(new BasicDBObject("time.check_date", -1))
        .limit(100);

但是,我需要此查询将结果分组最新check_date 条形码

1 个答案:

答案 0 :(得分:1)

聚合框架随时供您使用。运行以下聚合管道将为您提供所需的结果:

Mongo shell

pipeline = [
    {
        "$match": {
            "store_data.store_uuid": {
                "$in": [
                    "15a6cc90-081f-11e5-b213-001e6745ff8d",
                    "217b983b-5904-11e4-a1f0-00163ed23ec2",
                    "5337d78d-5904-11e4-a1f0-00163ed23ec2"
                ]
            },
            "product_related_data.product_uuid": "f44aa29d-09ce-4902-bf12-d45d44b3dfd0"
        }
    },
    { "$sort": { "time.check_date": -1 } },
    {
        "$group": {
            "_id": "$sensostrip_data.barcode",
            "stock_percentage": { "$first": "$stock_related_data.stock_percentage" },
            "store_uuid": { "$first": "$store_data.store_uuid" },
            "check_date": { "$first": "$time.check_date" }
        }
    },
    { "$limit": 100 }
];
db.readings.aggregate(pipeline);

Java测试实施

public class JavaAggregation {
    public static void main(String args[]) throws UnknownHostException {

        MongoClient mongo = new MongoClient();
        DB db = mongo.getDB("test");

        DBCollection coll = db.getCollection("readings");

        // create the pipeline operations, first with the $match
        DBObject match = new BasicDBObject("$match",
                        new BasicDBObject("store_data.store_uuid", new BasicDBObject("$in", StoreIds))
                            .append("product_related_data.product_uuid", productId)                         
                    );

        // sort pipeline
        DBObject sort = new BasicDBObject("$sort",
                            new BasicDBObject("time.check_date", -1)
                        );

        // build the $group operations
        DBObject groupFields = new BasicDBObject( "_id", "$sensostrip_data.barcode"); // group by barcode
        groupFields.put("stock_percentage", new BasicDBObject( "$first", "$stock_related_data.stock_percentage")); // get the first when ordered documents are grouped
        groupFields.put("store_uuid", new BasicDBObject( "$first", "$store_data.store_uuid"));
        groupFields.put("check_date", new BasicDBObject( "$first", "$time.check_date"));
        // append any other necessary fields

        DBObject group = new BasicDBObject("$group", groupFields);

        // limit step
        DBObject limit = new BasicDBObject("$limit", 100);

        // put all together 
        List<DBObject> pipeline = Arrays.asList(match, sort, group, limit);

        AggregationOutput output = coll.aggregate(pipeline);

        for (DBObject result : output.results()) {
            System.out.println(result);
        }
    }
}