दरअसल, दूसरा जवाब गलत है। आपके एग्रीगेटर के भीतर एक DBref फ़ील्ड पर एक लुकअप करना संभव है, और इसके लिए आपको मैप्रिड्यूज़ की आवश्यकता नहीं है।
समाधान
db.A.aggregate([
{
$project: {
B_fk: {
$map: {
input: {
$map: {
input:"$bid",
in: {
$arrayElemAt: [{$objectToArray: "$$this"}, 1]
},
}
},
in: "$$this.v"}},
}
},
{
$lookup: {
from:"B",
localField:"B_fk",
foreignField:"_id",
as:"B"
}
}
])
परिणाम
{
"_id" : ObjectId("59bb79df1e9c00162566f581"),
"B_fk" : null,
"B" : [ ]
},
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"B_fk" : [
ObjectId("582abcd85d2dfa67f44127e0"),
ObjectId("582abcd85d2dfa67f44127e1")
],
"B" : [
{
"_id" : ObjectId("582abcd85d2dfa67f44127e0"),
"status" : NumberInt("1"),
"seq" : NumberInt("0")
}
]
}
संक्षिप्त व्याख्या
$map के साथ DBRefs के माध्यम से लूप करें, प्रत्येक DBref को एक सरणी में तोड़ें, केवल $id फ़ील्ड रखें, फिर k:v प्रारूप को $$this.v से मुक्त करें, केवल ObjectId रखते हुए और बाकी सभी को हटा दें। अब आप ObjectId पर देख सकते हैं।
चरण-दर-चरण स्पष्टीकरण
एग्रीगेटर के भीतर, एक DBRef BSON प्रकार को दो या तीन क्षेत्रों (रेफरी, आईडी और डीबी) के साथ एक वस्तु की तरह नियंत्रित किया जा सकता है।
यदि आप करते हैं:
db.A.aggregate([
{
$project: {
First_DBref_as_array: {$objectToArray:{$arrayElemAt:["$bid",0]}},
Second_DBref_as_array: {$objectToArray:{$arrayElemAt:["$bid",1]}},
}
},
])
यह परिणाम है:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"First_DBref_as_array : [
{
"k" : "$ref",
"v" : "B"
},
{
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
],
"Second_DBref_as_array" : [
{
"k" : "$ref",
"v" : "B"
},
{
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
]
}
एक बार जब आप एक dbref को एक सरणी में बदल देते हैं, तो आप केवल इंडेक्स 1 पर मान को क्वेरी करके बेकार क्षेत्रों से छुटकारा पा सकते हैं:
db.A.aggregate([
{
$project: {
First_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
Second_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
}
},
])
परिणाम:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"First_DBref_as_array" : {
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
},
"Second_DBref_as_array" : {
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
}
फिर आप अंत में "$myvalue.v" की ओर इशारा करके अपने इच्छित मान तक पहुंच सकते हैं, ठीक इसी तरह
db.A.aggregate([
{
$project: {
first_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
second_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
}
},
{
$project: {
first_DBref_as_ObjectId: "$first_DBref_as_array.v",
second_DBref_as_ObjectId: "$second_DBref_as_array.v"
}
}
])
परिणाम:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"first_DBref_as_ObjectId" : ObjectId("582abcd85d2dfa67f44127e0"),
"second_DBref_as_ObjectId" : ObjectId("582abcd85d2dfa67f44127e0")
}
जाहिर है, एक सामान्य पाइपलाइन में, आपको नेस्टेड $map का उपयोग करके इन सभी अनावश्यक चरणों की आवश्यकता नहीं है, आप एक ही परिणाम में एक ही परिणाम प्राप्त कर सकते हैं:
db.A.aggregate([
{
$project: {
B_fk: { $map : {input: { $map: { input:"$bid",
in: { $arrayElemAt: [{$objectToArray: "$$this"}, 1 ]}, } },
in: "$$this.v"}},
}
},
])
परिणाम:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"B_fk" : [
ObjectId("582abcd85d2dfa67f44127e0"),
ObjectId("582abcd85d2dfa67f44127e1")
]
}
मुझे आशा है कि स्पष्टीकरण पर्याप्त स्पष्ट है, अगर पूछने में संकोच न करें।