我是新手,我的文档看起来像下面
{
Abc : [
{ _id : 1 , val : "somevalue" },
{ _id : 2 , val : "new value" },
{ _id : 3 , val : "new new value" }
],
Xyz : [
{ _id : 1 , val : 3456},
{ _id : 2 , val : 7689 },
{ _id : 3 , val : 21342}
],
Ghi : [
{ _id : 1 , val : "somevalue" },
{ _id : 2 , val : "new value" },
{ _id : 3 , val : "new new value" }
],
}
每个字段值应该通过Max _id过滤,即Abc: " new new value "
结果输出应该看起来像
{
_id : 1
Abc : "new new value",
Xyz : 21342,
Ghi : "new new value"
}
注意:字段可能不同或可能不存在于db
如果您正在查看.find()
的标准投影,那么确实没有太多的选项可以"排序"或"平坦化"数组成员,但如果元素已经按顺序排列,这是您最快的选择:
db.test.find({},{
"Abc": { "$slice": -1 },
"Ghi": { "$slice": -1 },
"Xyz": { "$slice": -1 }
})
与它的输出:
{
"_id" : ObjectId("537d876dbeeccb8f75e1ef9a"),
"Abc" : [{ "_id" : 3, "val" : "new new value" }],
"Xyz" : [{ "_id" : 3, "val" : 21342 }],
"Ghi" : [{ "_id" : 3, "val" : "new new value" }]
}
{
"_id" : ObjectId("537d87fe348f6339113e85ae"),
"Abc" : [{ "_id" : 3, "val" : "new new value" }],
"Ghi" : [{ "_id" : 3, "val" : "new new value" }]
}
如果您准备指定所有可能的字段,则可以使用聚合框架做这样的事情:
db.test.aggregate([
{ "$project": {
"Abc": { "$ifNull": [ "$Abc", [ false ] ] },
"Ghi": { "$ifNull": [ "$Ghi", [ false ] ] },
"Xyz": { "$ifNull": [ "$Xyz", [ false ] ] }
}},
{ "$unwind": "$Abc" },
{ "$unwind": "$Ghi" },
{ "$unwind": "$Xyz" },
{ "$sort": { "Abc._id": -1, "Ghi._id": -1, "Xyz": -1 } },
{ "$group": {
"_id": "$_id",
"Abc": { "$first": "$Abc.val" },
"Ghi": { "$first": "$Ghi.val" },
"Xyz": { "$first": "$Xyz.val" }
}}
])
本质上是把一个[ false ]
数组在那里,如果该字段不存在,使用 $ifNull
操作符来阻止后来的 $unwind
语句爆发。这是否是您的解决方案,具体情况可能有所不同。输出:
{
"_id" : ObjectId("537d876dbeeccb8f75e1ef9a"),
"Abc" : "new new value",
"Ghi" : "new new value",
"Xyz" : 21342
}
{
"_id" : ObjectId("537d87fe348f6339113e85ae"),
"Abc" : "new new value",
"Ghi" : "new new value",
"Xyz" : null
}
或者你可以用mapReduce做一些更复杂的事情,即使没有实际的减少:
db.test.mapReduce(
function () {
for ( var k in this ) {
if ( k === '_id' )
continue;
this[k].sort(function(a, b) {
if ( a._id < b._id ) {
return -1;
} else if ( a._id > b._id ) {
return 1;
}
return 0;
});
this[k] = this[k].slice(-1)[0].val;
}
var id = this._id;
delete this["_id"];
emit( id, this );
},
function(){},
{
"out": { "inline": 1 }
}
)
它有可怕的mapReduce输出,但至少你可以灵活地使用你在文档中的"键":
"results" : [
{
"_id" : ObjectId("537d876dbeeccb8f75e1ef9a"),
"value" : {
"Abc" : "new new value",
"Xyz" : 21342,
"Ghi" : "new new value"
}
},
{
"_id" : ObjectId("537d87fe348f6339113e85ae"),
"value" : {
"Abc" : "new new value",
"Ghi" : "new new value"
}
}
]
所以这是考虑到他们各自的优点和缺点的几种方法,但也是一种完成工作的方法。