首页 > 解决方案 > 自定义字段与 MONGO 进行聚合

问题描述

是否可以使用 java 和 mongoDB 将 2 个自定义字段(我的集合中不存在)添加到聚合组查询中?我的方法如下,但它不起作用

    Double custom_calculated_field1 = 0d;
    Double custom_calculated_field2 = 0d;
    Document customGroup_fields = new Document();
    customGroup_fields.append("customer_id", "$customer_id");
    //custom_calculated fields
    customGroup_fields.append("custom_calculated_field1", custom_calculated_field1);
    customGroup_fields.append("custom_calculated_field2", custom_calculated_field2);
         AggregateIterable<Document> customers_results = customerID.aggregate(
            Arrays.asList(
                    Aggregates.match(values),
                    Aggregates.group(customGroup_fields)
            ));

标签: javamongodb

解决方案


这是您构建聚合的方式的问题。您可以在此处阅读有关 Mongo 聚合文档的更多信息:https ://docs.mongodb.com/manual/aggregation/

实际上,您假设您的管道知道您要执行的操作。然而,管道的工作方式与 unix 管道的工作方式非常相似|。它执行任何命令并将输出传递给下一个。所以你需要告诉它你的比赛是比赛,小组是小组。我有一个例子DocumentDBObjectDBObject我相信最新的方法在哪里。考虑这个例子:

  @Test
    public void testAggProjection() { 
        DBCollection collection = template.getCollection("test-collection");

        DBObject ob = new BasicDBObject(ImmutableMap.of("test", "value1", "something", "here"));
        DBObject ob2 = new BasicDBObject(ImmutableMap.of("test", "value1", "hello", "world"));
        DBObject ob3 = new BasicDBObject(ImmutableMap.of("test", "value2", "other", "fields"));
        WriteResult insert = collection.insert(ob, ob2, ob3);
        Assert.assertEquals(3, insert.getN());

        DBObject match = new BasicDBObject("$match", new BasicDBObject("test", "value1")); // match the test value 
        Map<String, Object> grouping = new HashMap<>();
        grouping.put("_id", "$test");
        grouping.put("my_count", new BasicDBObject("$sum", 1));
        DBObject group = new BasicDBObject("$group", grouping); // group by 

        AggregationOutput aggregate = collection.aggregate(match, group);
        System.out.println(aggregate.results());
        DBObject next = aggregate.results().iterator().next();
        Assert.assertTrue(next.containsField("_id"));
        Assert.assertTrue(next.containsField("my_count"));


        // with documents raw 
        MongoClient mc = (MongoClient) client;
        MongoCollection<Document> collection2 = mc.getDatabase(template.getDb().getName()).getCollection("test-collection");

        Document dob = new Document(ImmutableMap.of("test", "value1", "something", "here"));
        Document dob2 = new Document(ImmutableMap.of("test", "value1", "hello", "world"));
        Document dob3 = new Document(ImmutableMap.of("test", "value2", "other", "fields"));

        collection2.insertMany(Arrays.asList(dob, dob2, dob3));

        long count = collection2.count();
        Assert.assertEquals(3, count);

        Document match2 = new Document("$match", new Document("test", "value1"));
        Document group2 = new Document("$group", ImmutableMap.of("_id", "$test", "my_count", new Document("$sum", 1)));

        AggregateIterable<Document> aggregate2 = collection2.aggregate(Arrays.asList(match2, group2));
        Document next2 = aggregate2.iterator().next();
        Assert.assertTrue(next2.get("_id") != null);
        Assert.assertTrue(next2.get("my_count") != null);
    }

这是一个工作单元测试。这样做是(在这两种情况下):

  • 创建一个新集合并插入 3 个文档。
  • 将它们与一个匹配项、匹配 2 个文档和一个我们计算找到的对象的组聚合起来。

对您来说重要的部分在这里:

Document match2 = new Document("$match", new Document("test", "value1"));
        Document group2 = new Document("$group", ImmutableMap.of("_id", "$test", "my_count", new Document("$sum", 1)));

        AggregateIterable<Document> aggregate2 = collection2.aggregate(Arrays.asList(match2, group2));

在我的match2group2文档中,我将聚合执行的阶段定义为$match$group

然后生成的 Json 是:

Document{{_id=value1, my_count=2}}

我希望这会有所帮助!

请注意,_id组内的字段是强制性的。

阿图尔


推荐阅读