Home > Blockchain >  How to read in this MongoDb field that contains dynamic children fields, in JavaScript?
How to read in this MongoDb field that contains dynamic children fields, in JavaScript?

Time:04-04

Given the following MongoDB document structure (which I cannot change), I'm not sure how to read this in JavaScript?

  • so loginHistory is the main field name. It contains an Object type (okay???)

  • it can then contain multiple children fields (this above example has only ONE child), which are arrays. These field names are dynamic, but unique.

  • the 'array' content is a C# DateTimeOffset , I've been told.

So in the example above, Jane is the field and the value is an Array, but really it's a DateTime.Offset.

Here's another document I've found:

  • 4x fields

So i don't know how to read this with node/JavaScript. Oh - and the field loginHistory might not exist on some documents, also :(

So given that existing document schema/structure, I need to somehow read in each loginHistory value and then create a new document (which i'll do other stuff with later).

This is some JavaScript code I tried, but doesn't work:

    users.loginHistory.forEach(loginHistory => { 
        // do stuff, like create a new { id = users._id, name = "Jane", createdOn = "that date/time offset" }
    }

CodePudding user response:

Assuming we have an input set of docs like the screen shots e.g.:

var r = [
    {
        loginHistory: {
            "Jane": [ 1648835363929,  0 ],
            "Bob": [ 1648835363929,  0 ]
        }
    },
    {
        noLoginHistory: "nope"
    },
    {
        loginHistory: {
            "Dan": [ 1648835363929,  0 ],
            "Dave": [ 1648835363929,  0 ],
            "Jane": [ 1648835363929,  0 ]
        }
    }
];

then the following pipeline will create new, "converted" docs in a collection named foo2.

db.foo.aggregate([
    // OK if loginHistory does not exist.  X will be set to null                     
    // and the $unwind will not produce anything:                                    
    {$project: {X: {$objectToArray: "$$ROOT.loginHistory"} }},
    {$unwind: "$X"},

    // Now we have individual docs of                                                
    //   X: {k: name, v: the array}                                                  
    // The OP wanted to make a new doc for each one.  I don't know                   
    // what function to apply to turn X.v[0] into a MongoDB datetime                 
    // because I don't know what that big int (637807576034080256) is                
    // supposed to be so I used regular ms since epoch for the example               
    // instead.  The OP will have to get more creative with division                 
    // and such to turn 637807576034080256 into something "toDate-able"              
    // in MongoDB.  You *could* store the big int as is but it is always             
    // good to try to turn a datetime into a real datetime in mongodb.               
    {$project: {
        _id: false,
        name: '$X.k',
        createdOn: {$toDate: {$arrayElemAt:['$X.v',0]}}
    }}

    // Now we have docs like :                                                       
    // {name: "Jane", createdOn: ISODate(...) }                                     
    // By calling $out to a new collection, a new _id will be assigned               
    // to each:                                                                      
    ,{$out: "foo2"}
]);
  • Related