Home > Software engineering >  converting an array of objects to a virtual mongodb collection
converting an array of objects to a virtual mongodb collection

Time:12-08

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.

  • Related