在Aggregation Pipeline Stages中,有一個$lookup函數,具體的用法如下
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
而如果localField是 DBRef里面的$id,那么則不能lookup
$lookup:
{
from: "tableA",
localField: "tableA.$id",
foreignField: "_id",
as:"tableA"
}
}
會返回如下錯誤
assert: command failed:
{ "ok" : 0, "errmsg" : "FieldPath field names may not start with '$'.", "code" : 16410 }
原因是管道函數中限制了fieldName不能以$開始,所以此處會報錯。
When change notification is first stage in aggregation any data manipulation that's done in that pipeline may need to project or check/use the value of "o.$__" field ($set, $unset, etc).
解決辦法:在lookup前加入下面管道代碼生成一個去掉$的field
{$addFields:{"newfoo":
{$arrayToObject:{$map:{
input:{$objectToArray:"$foo"},
in:{
k:{$cond:[
{$eq:[{"$substrCP":["$$this.k",0,1]},{$literal:"$"}]},
{$substrCP:["$$this.k",1,{$strLenCP:"$$this.k"}]},
"$$this.k"
]},
v:"$$this.v"
}
}}}
}}
此處的newfoo為新增的field的別名,foo為DBRef的field,其它代碼為固定寫法,也就是可以復制此處代碼修改兩個地方,效果如下
before
{
"foo":{
"$ref":"foo",
"$id":"123"
}
}
after
{
"foo":{
"$ref":"foo",
"$id":"123"
},
"newfoo":{
"ref":"foo",
"id":"123"
}
}
那么我們就可以開心的使用lookup了。
參考官方還在OPEN的defectSERVER-14466,也許以后可以用$開頭作為fieldName使用,但是暫時的代替方法為上述方法.