繁体   English   中英

如何使用MongoDB Java驱动程序对ISODate属性的dayOfYear进行分组?

[英]How to use MongoDB Java driver to group by dayOfYear on ISODate attributes?

如何使用mongodb java驱动程序比较两个ISODate对象的dayOfYear?

这是我的文档

{"name": "hello", "count": 4, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "hello", "count": 5, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "goodbye", "count": 6, "TIMESTAMP": ISODate("2017-10-01T02:00:35.098Z")}
{"name": "foo", "count": 6, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}

我想比较“ TIMESTAMP”中的日期以执行一些汇总

 Bson match = Aggregates.match(eq("name": "hello"));
 Bson group = Aggregates.group(new Document("name", "$name"), Accumulators.sum("total", 1));

collection.aggregate(Arrays.asList(match, group))

现在,我不确定如何对属于特定日期的所有记录进行此汇总?

所以我对“ 2017-10-02”的预期结果是

[{"_id": {"name":"hello"}, "total": 9}, {"_id": {"name":"foo"}, "total": 6}]

鉴于以下文件:

{"name": "hello", "count": 4, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "hello", "count": 5, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "goodbye", "count": 6, "TIMESTAMP": ISODate("2017-10-01T02:00:35.098Z")}
{"name": "foo", "count": 6, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}

以下命令...

db.getCollection('dayOfYear').aggregate([

    // project dayOfYear as an attribute
    { $project: { name: 1, count: 1, dayOfYear: { $dayOfYear: "$TIMESTAMP" } } },

    // match documents with dayOfYear=275
    { $match: { dayOfYear: 275 } },

    // sum the count attribute for the selected day and name
    { $group : { _id : { name: "$name" }, total: { $sum: "$count" } } } 

])

... 将返回:

{
    "_id" : {
        "name" : "foo"
    },
    "total" : 6
}

{
    "_id" : {
        "name" : "hello"
    },
    "total" : 9
}

认为这符合您在OP中表达的要求。

这是使用MongoDB Java驱动程序表达的相同命令:

MongoCollection<Document> collection = mongoClient.getDatabase("stackoverflow").getCollection("dayOfYear");

Document project = new Document("name", 1)
        .append("count", 1)
        .append("dayOfYear", new Document("$dayOfYear", "$TIMESTAMP"));

Document dayOfYearMatch = new Document("dayOfYear", 275);

Document grouping = new Document("_id", "$name").append("total", new Document("$sum", "$count"));

AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
        new Document("$project", project),
        new Document("$match", dayOfYearMatch),
        new Document("$group", grouping)
));

for (Document document : documents) {
    logger.info("{}", document.toJson());
}

根据此评论进行更新

项目的问题之一是它仅包含您指定的字段。 以上输入仅是示例。 我的文档中有100个字段,我无法将每个字段都分隔开,因此,如果我使用项目,则除了“ dayOfYear”字段外,还必须指定所有100个字段。 – user1870400 11分钟前

您可以使用以下命令返回相同的输出,但没有$project阶段:

db.getCollection('dayOfYear').aggregate([
    // ignore any documents which do not match dayOfYear=275
    { "$redact": {
        "$cond": {
             if: { $eq: [ { $dayOfYear: "$TIMESTAMP" }, 275 ] },
             "then": "$$KEEP",
             "else": "$$PRUNE"
        }
    }},

    // sum the count attribute for the selected day
    { $group : { _id : { name: "$name" }, total: { $sum: "$count" } } } 

])

这是“ Java形式”的命令:

MongoCollection<Document> collection = mongoClient.getDatabase("stackoverflow").getCollection("dayOfYear");

Document redact = new Document("$cond", new Document("if", new Document("$eq", Arrays.asList(new Document("$dayOfYear", "$TIMESTAMP"), 275)))
        .append("then", "$$KEEP")
        .append("else", "$$PRUNE"));

Document grouping = new Document("_id", "$name").append("total", new Document("$sum", "$count"));

AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
        new Document("$redact", redact),
        new Document("$group", grouping)
));

for (Document document : documents) {
    logger.info("{}", document.toJson());
}

注意:根据集合的大小/您的非功能性要求/等,您可能要考虑这些解决方案的性能,并且(a)在开始投影/编辑之前添加匹配阶段,或者(b)将dayOfYear提取为自己的属性,这样您就可以完全避免这种复杂性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM