如何在MongoDB中的文档内聚合数组并获取多个条件的计数?

时间:2015-12-21 14:55:13

标签: c# json xml mongodb aggregation-framework

我正在编写一个程序,该程序接收车辆刷新数据的XML文件并将其转换为JSON,以便将其存储在MongoDB数据库中。 XML以这样的方式开始:

<FlashReportGeneratorTag>
    <VehicleEntry>
        <VehicleStatus>PASSED</VehicleStatus>
    </VehicleEntry>
    <VehicleEntry>
        <VehicleStatus>PASSED</VehicleStatus>
    </VehicleEntry>
</FlashReportGeneratorTag>

在我将其转换为JSON并添加项目标识符后,我留下了这样的格式:

{
    "FlashReportGeneratorAddedTag" : {
        "VehicleEntry" : [
            {
                "VehicleStatus" : "PASSED"
            }, 
            {
                "VehicleStatus" : "PASSED"
            }
        ]
    },
    "project_id" : "1234"
}

我想做的是获得项目1234的每个文件中通过的车辆总数和车辆数量的总数,但我没有运气。

我已经尝试过使用我所知道的基本聚合技巧,但我不能简单地按project_id进行分组,因为当我需要聚合其中的数组时,它会按文档分组。我还没有找到任何资源告诉你是否能够或不能一次聚合两个值(得到传递的总和和失败计数的总和)。

作为最后的手段,我可​​以改变文档样式,让每个VehicleEntry都是它自己的文档,但是如果可以的话,我想采用并存储XML。

编辑使用展开我能够为我正在寻找的阵列设置聚合:

var aggregate = collection.Aggregate().Match(new BsonDocument { { "project_id", "1234" } }).Unwind(i => i["FlashReportGeneratorAddedTag.VehicleEntry"]);

但是,我无法找到对这些进行分组的正确方法,以便在整个阵列中获取通过/失败计数。我假设有一些方法我需要使用匹配功能,但我无法在不排除这两个条件之一的情况下弄清楚如何做到这一点。我是否必须运行聚合两次,一次是传递,一次是失败?

1 个答案:

答案 0 :(得分:1)

感谢JohnnyHK的暗示和更多的挖掘,我能够解决这个问题。首先,我必须使用Unwind方法来展开Vehicleentry数组,以便对其进行聚合:

var aggregate = collection.Aggregate().Match(new BsonDocument { { "project_id", "1234" } })
   .Unwind(i => i["FlashReportGeneratorAddedTag.VehicleEntry"])

有一次,我能够嵌套BsonDocuments以便根据条件求和。为了得到通过的计数,我使用了这个:

{ "passed", new BsonDocument { { "$sum", new BsonDocument { { "$cond", new BsonArray { new BsonDocument { { "$eq", new BsonArray { "$FlashReportGeneratorAddedTag.VehicleEntry.VehicleStatus", "PASSED" } } }, 1, 0 } } } } } }

同样,我添加了一个失败的标签。整件事(尚未格式化)是这样的:

var collection = _database.GetCollection<BsonDocument>(Vehicles);
var aggregate = collection.Aggregate()
.Match(new BsonDocument{ { "project_id", "1234" } })
.Unwind(i => i["FlashReportGeneratorAddedTag.VehicleEntry"])
.Group(new BsonDocument
{ 
    { "_id", "$project_id" },
    { "passed", new BsonDocument
        { { "$sum", new BsonDocument
                { { "$cond", new BsonArray
                        { new BsonDocument
                            { { "$eq", new BsonArray 
                                {
                                    "$FlashReportGeneratorAddedTag.VehicleEntry.VehicleStatus", 
                                    "PASSED"
                                } }
                                },
                            1,
                            0 } } } } } 
    },
    { "failed", new BsonDocument
        { { "$sum", new BsonDocument
                { { "$cond", new BsonArray
                        { new BsonDocument
                            { { "$eq", new BsonArray 
                                {
                                    "$FlashReportGeneratorAddedTag.VehicleEntry.VehicleStatus", 
                                    "FAILED"
                                } }
                                },
                            1,
                            0 } } } } } 
    },
});
var results = await aggregate.ToListAsync();