我坚持使用MongoDB分组和项目自定义字段。我有以下集合:
{
"DescId" : "1",
"Desc" : "Testing",
"ParentId" : "null",
"Order" : 1.0,
"Type" : "A",
"Parent" : null
}
{
"DescId" : "1.1",
"Desc" : "Testing Child 1",
"ParentId" : "1",
"Order" : 1.0,
"Type" : "B",
"Parent" : "Testing"
}
{
"DescId" : "1.2",
"Desc" : "Testing Child 2",
"ParentId" : "1",
"Order" : 2.0,
"Type" : "B",
"Parent" : "Testing"
}
我根据Type,DescId,Desc字段和投影的DescId和Desc完成了以下分组
db.getCollection("GenericData").aggregate(
[
{
"$group" : {
"_id" : {
"Type" : "$Type",
"DescId" : "$DescId",
"DescName" : "$Desc"
}
}
},
{
"$project" : {
"_id" : 0.0,
"Id" : "$_id.DescId",
"Name" : "$_id.DescName",
"Type" : "$_id.Type"
}
}
],
{
"allowDiskUse" : false
}
);
这是我得到的输出:
{
"Id" : "1.2",
"Name" : "Testing Child 2",
"Type" : "B"
}
{
"Id" : "1.1",
"Name" : "Testing Child 1",
"Type" : "B"
}
{
"Id" : "1",
"Name" : "Testing",
"Type" : "A"
}
是否可以基于类型字段来投影字段,例如将类型值与字段名称连接如下:
{
"A" + "Id" : "1",
"A" + "Name" : "Testing"
},
{
"B" + "Id" : "1.1",
"B" + "Name" : "Testing Child 1"
}
{
"B" + "Id" : "1.2",
"B" + "Name" : "Testing Child 2"
}
要重命名对象的键,必须使用$objectToArray和$arrayToObject运算符。第一个可以将您的$$ROOT
对象转换为键和值数组。然后你可以应用$map修改键(使用$concat)和$filter来排除Type
键。然后,您可以使用$arrayToObject
将该数组转换回对象,并使用$replaceRoot将该对象提升为根级别。因此,您可以将以下阶段添加到聚合管道:
db.GenericData.aggregate([
{
$replaceRoot: {
newRoot: {
$arrayToObject: {
$map: {
input: {
$filter: {
input: { $objectToArray: "$$ROOT" },
as: "kv",
cond: { $in: [ "$$kv.k", [ "Id", "Name" ] ] }
}
},
as: "kv",
in: {
k: { $concat: [ "$Type", "$$kv.k" ] },
v: "$$kv.v"
}
}
}
}
}
}
])
输出:
{ "BId" : "1.2", "BName" : "Testing Child 2" }
{ "BId" : "1.1", "BName" : "Testing Child 1" }
{ "AId" : "1", "AName" : "Testing" }
编辑:如果您想明确指定应投影哪些属性,您可以在$in中使用$filter
运算符