MongoDB: 项目使用数组字段
MongoDB: Project using array fields
我有一个这样的集合:每个文档包含 Message
字段,该字段又包含 Fields
数组。 Fields
数组下的每个文档都有 Value
和 Name
属性。
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Message" : {
"Fields" : [
{
"Value" : 131,
"Name" : "Options",
},
{
"Value" : 8,
"Name" : "Length",
}
]
}
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Message" : {
"Fields" : [
{
"Value" : 65,
"Name" : "Options",
},
{
"Value" : 13,
"Name" : "Length",
},
{
"Value" : 101,
"Name" : "Width",
}
]
}
}
]
在使用 db.Collection.find({})
找到文档后,我想这样投影 - 它解析 Message.Fields
下面的每个 Field
并使用 Type
将它们投影到新文档中属性 名称和 Value
作为值。输出如下所示:
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Length" : 8
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Length" : 13,
"Width" : 101
},
]
这是否可以使用 function()
或 aggregate
或 MongoDB 中的任何其他方式实现?
您可以使用aggregation and the $cond
运算符
db.collection.aggregate(
[
{ $unwind: "$Message.Fields" },
{ $project: { fields: "$Message.Fields" }},
{ $project:
{
Option:
{
$cond: [{ $eq: [ "$fields.Name", "Options" ]}, "$fields.Value", 0 ]
},
Length:
{
$cond: [{ $eq: [ "$fields.Name", "Length" ]}, "$fields.Value", 0 ]
},
Width:
{
$cond: [{ $eq: [ "$fields.Name", "Width" ]}, "$fields.Value", 0]
}
}
},
{ $group: {
_id: "$_id",
Options: { $sum: "$Option" },
Width: { $sum: "$Width" },
Length: { $sum: "$Length" }
}
}
]
)
结果:
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Width" : 101,
"Length" : 13
}
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Width" : 0,
"Length" : 8
}
我正在使用以下脚本生成上述结果 [=11=]。
var result=[];
var cursor=db.collection.find().forEach(
function(myDoc)
{
print(myDoc)
var obj1={};
obj1._id=myDoc._id;
var len_of_fields=myDoc.Message.Fields.length;
if(len_of_fields==2)
{
var j=0;
obj1.Options=myDoc.Message.Fields[j].Value;
obj1.Length=myDoc.Message.Fields[j+1].Value;
result.push(obj1)
}
else if(len_of_fields==3)
{
var j=0;
obj1.Options=myDoc.Message.Fields[j].Value;
obj1.Length=myDoc.Message.Fields[j+1].Value;
obj1.Width=myDoc.Message.Fields[j+2].Value;
result.push(obj1)
}
print( "DOC: ", result);
}
);
使用 MongoDB 版本 3.4.4 和更新版本,使用 $arrayToObject
将 "$Message.Fields"
数组转换为所需的对象,但在
使用上述运算符,您必须使用 $map
将数组中对象的属性重塑为键 k 和 var。这是
$arrayToObject
将列表转换为 key/value 对的对象所必需的。
转换对象后,您可以将其与 _id
字段合并,然后使用 $replaceRoot
.[=26 将根替换为合并后的文档=]
以下管道展示了这种方法:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ _id: "$_id" },
{ "$arrayToObject": {
"$map": {
"input": "$Message.Fields",
"in": {
"k": "$$this.Name",
"v": "$$this.Value"
}
}
} }
]
}
} }
])
使用 map()
method from the find()
游标,它将一个函数应用于游标访问的每个文档,并将连续应用中的 return 值收集到一个数组中,其中您可以将所需的字段投影到所需的结果中:
var result = db.collection.find().map(function (doc){
var obj = {};
obj["_id"] = doc._id
doc.Message.Fields.forEach(function (field){
obj[field.Name] = field.Value;
})
return obj;
});
printjson(result);
输出:
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Length" : 8
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Length" : 13,
"Width" : 101
}
]
我有一个这样的集合:每个文档包含 Message
字段,该字段又包含 Fields
数组。 Fields
数组下的每个文档都有 Value
和 Name
属性。
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Message" : {
"Fields" : [
{
"Value" : 131,
"Name" : "Options",
},
{
"Value" : 8,
"Name" : "Length",
}
]
}
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Message" : {
"Fields" : [
{
"Value" : 65,
"Name" : "Options",
},
{
"Value" : 13,
"Name" : "Length",
},
{
"Value" : 101,
"Name" : "Width",
}
]
}
}
]
在使用 db.Collection.find({})
找到文档后,我想这样投影 - 它解析 Message.Fields
下面的每个 Field
并使用 Type
将它们投影到新文档中属性 名称和 Value
作为值。输出如下所示:
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Length" : 8
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Length" : 13,
"Width" : 101
},
]
这是否可以使用 function()
或 aggregate
或 MongoDB 中的任何其他方式实现?
您可以使用aggregation and the $cond
运算符
db.collection.aggregate(
[
{ $unwind: "$Message.Fields" },
{ $project: { fields: "$Message.Fields" }},
{ $project:
{
Option:
{
$cond: [{ $eq: [ "$fields.Name", "Options" ]}, "$fields.Value", 0 ]
},
Length:
{
$cond: [{ $eq: [ "$fields.Name", "Length" ]}, "$fields.Value", 0 ]
},
Width:
{
$cond: [{ $eq: [ "$fields.Name", "Width" ]}, "$fields.Value", 0]
}
}
},
{ $group: {
_id: "$_id",
Options: { $sum: "$Option" },
Width: { $sum: "$Width" },
Length: { $sum: "$Length" }
}
}
]
)
结果:
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Width" : 101,
"Length" : 13
}
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Width" : 0,
"Length" : 8
}
我正在使用以下脚本生成上述结果 [=11=]。
var result=[];
var cursor=db.collection.find().forEach(
function(myDoc)
{
print(myDoc)
var obj1={};
obj1._id=myDoc._id;
var len_of_fields=myDoc.Message.Fields.length;
if(len_of_fields==2)
{
var j=0;
obj1.Options=myDoc.Message.Fields[j].Value;
obj1.Length=myDoc.Message.Fields[j+1].Value;
result.push(obj1)
}
else if(len_of_fields==3)
{
var j=0;
obj1.Options=myDoc.Message.Fields[j].Value;
obj1.Length=myDoc.Message.Fields[j+1].Value;
obj1.Width=myDoc.Message.Fields[j+2].Value;
result.push(obj1)
}
print( "DOC: ", result);
}
);
使用 MongoDB 版本 3.4.4 和更新版本,使用 $arrayToObject
将 "$Message.Fields"
数组转换为所需的对象,但在
使用上述运算符,您必须使用 $map
将数组中对象的属性重塑为键 k 和 var。这是
$arrayToObject
将列表转换为 key/value 对的对象所必需的。
转换对象后,您可以将其与 _id
字段合并,然后使用 $replaceRoot
.[=26 将根替换为合并后的文档=]
以下管道展示了这种方法:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ _id: "$_id" },
{ "$arrayToObject": {
"$map": {
"input": "$Message.Fields",
"in": {
"k": "$$this.Name",
"v": "$$this.Value"
}
}
} }
]
}
} }
])
使用 map()
method from the find()
游标,它将一个函数应用于游标访问的每个文档,并将连续应用中的 return 值收集到一个数组中,其中您可以将所需的字段投影到所需的结果中:
var result = db.collection.find().map(function (doc){
var obj = {};
obj["_id"] = doc._id
doc.Message.Fields.forEach(function (field){
obj[field.Name] = field.Value;
})
return obj;
});
printjson(result);
输出:
[
{
"_id" : ObjectId("55711efed0103b1598140076"),
"Options" : 131,
"Length" : 8
},
{
"_id" : ObjectId("55711efed0103b1598140077"),
"Options" : 65,
"Length" : 13,
"Width" : 101
}
]