由于$
位置运算符不起作用 2 级深度嵌套数组,因此我正在使用替代模式为嵌套数组启用更新功能。
我有一个嵌套文档如下
{
'_id' : 1234,
'bio' : {
'achievements' : {
'Yhg87Hghg65' : {
'title' : 'Achievement 1',
'score' : 95,
'year' : 2004
},
'67gjfygt8Hd' : {
'title' : 'Achievement 2',
'score' : 89,
'year' : 2003
},
'Lkoh8hHggf7' : {
'title' : 'Achievement 1',
'score' : 90,
'year' : 2005
}
}
}
}
现在,使用 mongodb 聚合管道,我可以在 PHP 中获取它,如下所示
$doc = $collection -> aggregate(
array(
'$match' => array(
'_id' => 1234
)
),
array(
'$project' => array(
'bio.achievements' => 1
)
)
);
到目前为止,一切正常。但我需要按年份对成就进行排序。在'$project'
之前使用普通'$sort'
是行不通的,因为成就不是数组,所以它们是值为数组的字段。如果有人知道如何实现它,请给我一些提示。
当你的对象在映射中时,在javascript中,你永远无法保证检索的顺序。MongoDb也没有任何内置方法来对地图的属性进行排序。因此,您需要在客户端进行排序。您的代码可能如下所示:
var result = db.collection.find({"_id":1234},{"bio.achievements":1}).
map(function(doc){
var achievements = (Object.keys(doc.bio.achievements)).
map(function(key){
doc.bio.achievements[key]["key"] = key;
return doc.bio.achievements[key];
});
achievements.sort(function(a,b){
return a.year-b.year;
})
doc.bio.achievements = achievements;
return doc;
})
话虽如此,存储有序对象的最佳方法是将它们存储在数组中。如果可以按如下方式更改架构:
{
'_id' : 1234,
'bio' : {
'achievements' : [
{ 'id':'Yhg87Hghg65',
'title' : 'Achievement 1',
'score' : 95,
'year' : 2004
},
{
'id':'67gjfygt8Hd',
'title' : 'Achievement 2',
'score' : 89,
'year' : 2003
},
{ 'id':'Lkoh8hHggf7',
'title' : 'Achievement 1',
'score' : 90,
'year' : 2005
}
]
}
}
您可以轻松聚合所需的结果:
db.collection.aggregate([
{$match:{"_id":1234}},
{$unwind:"$bio.achievements"},
{$sort:{"bio.achievements.year":1}},
{$group:{"_id":"$_id","achievements":{$push:"$bio.achievements"}}}
])
样品 o/p:
{
"_id" : 1234,
"achievements" : [
{
"id" : "67gjfygt8Hd",
"title" : "Achievement 2",
"score" : 89,
"year" : 2003
},
{
"id" : "Yhg87Hghg65",
"title" : "Achievement 1",
"score" : 95,
"year" : 2004
},
{
"id" : "Lkoh8hHggf7",
"title" : "Achievement 1",
"score" : 90,
"year" : 2005
}
]
}
由于 $ 位置运算符不起作用 2 级深度嵌套数组,我 我使用替代架构为嵌套启用更新功能 数组。
您需要以这样的方式设计您的架构,以便可以使用 $
运算符进行更新,就发布的示例而言,可以使用位置运算符进行更新,类似于下面的操作:
db.collection.update({"bio.achievements.id":"Yhg87Hghg65"},
{$set:{"bio.achievements.$.year":2006}});