let serviceData = await getServiceData();
I'm fetching some data from an external service which is an array of objects like:
[
{
_id
x
y
},
...
]
Is there any way to use this result in lookup stage without actually creating it as a collection in database? I want to create an aggregation for another collection with a schema like
new Schema({
_id
a
b
);
and in that do a lookup like:
{
from: serviceData,
localField: "_id",
foreignField: "_id",
as: "data"
}
and finally get
[
{
_id
x
y
a
b
},
...
]
CodePudding user response:
Try this one:
{
$set: {
data: {
$filter: {
input: serviceData,
cond: { $eq: ["$$this._id", "$_id"] }
}
}
}
}
CodePudding user response:
You already have serviceData
in the client side code, so all you need to do is $match
into your target collection, then "join" the material on the client side like this:
var svcdata = [
{ _id: 1, x: 3, y: 7 },
{ _id: 2, x: 8, y: 9 }
];
// Create an array of _id from the given serviceData:
var zzz = svcdata.map(x => x['_id']);
// Create a key lookup dictionary (_id => rest of serviceData).
// All fields will be picked up; no need to enumerate
// x, y, z, etc.:
var svcdict = {};
svcdata.forEach(function(item) {
svcdict[item['_id']] = item;
});
// This is all you need to find the material in your collection:
c=db.foo.aggregate([
{$match: {_id: {$in: zzz} }}
]);
// As you pull each doc from the DB, key-match on _id and add it
// to the materal:
c.forEach(function(doc) {
doc['svcdata'] = svcdict[doc['_id']];
printjson(doc);
});
It ends up looking something like this:
{
"_id" : 1,
"name" : "N1",
"svcdata" : {
"_id" : 1,
"x" : 3,
"y" : 7
}
}
{
"_id" : 2,
"name" : "N2",
"svcdata" : {
"_id" : 2,
"x" : 8,
"y" : 9
}
}
This is a "safe" approach because you avoid name collisions of incoming serviceData
fields with fields in your docs, i.e. it is namespaced. Of course, you can at your choosing generically iterate over svcdict[doc[_id]]
and push each field into the "root" document coming from MongoDB.