简体   繁体   中英

Mongoose create a new document with catergorized sub documents

I've been going through the Mongoose docs, and I think I'm missing some fundamental understanding in how it works.

What I'm trying to do

I'm making a third party API call that returns a structure that looks like

Route
 |__Train 1 on Route
     |__Upcoming Station (with ID)
     |   |__Time to this station
     |__Upcoming Station (with ID)
     |   |__Time to this station
     ...
 |__Train 2
        ...

And my goal is to format it in a document as such

tableId : String,

stations : [{   
    stopId : String, 
    incoming : [{
        vehicleId : String,
        timeAway : { type: Number, min: 0, max: 3000 },
        lastUpdated : { type: Date, default: Date.now }
    }]
}],

What I'm trying currently is going through the received data for each train, and in that each upcoming station, and plug the estimated arrival time into the list of stations. The important part is that Train 1 and Train 2 may both be arriving at a given station, and I only want one station element with multiple predictions. The problem is, I can't do a findOneAndUpdate with an upsert, as the document doesn't exist yet.

From the doc on subdocs ( here ), I've tried push and addToSet, but these just create a subdocument for each prediction. For example I'll get:

[{
  stopId: 1234,
  incoming : [{
    vehicleId : 11,
    timeAway : 200
  }]
},
  stopId: 1234,
  incoming : [{
    vehicleId : 22,
    timeAway : 400
  }]
}]

Where I'm trying to get:

[{
  stopId: 1234,
  incoming : [{
    vehicleId : 11,
    timeAway : 200
  },{
    vehicleId : 22,
    timeAway : 400
  }]
}]

I feel like I'm missing some fundamental aspect of creating this document.

For data schema,

var StationSchema = new mongoose.Schema({
    tableId: String,
    stations: [{
        stopId: String,
        incoming: [{
            vehicleId: String,
            timeAway: {type: Number, min: 0, max: 3000},
            lastUpdated: {type: Date, default:  Date.now}
        }]
    }]
});

Save data through

var s = new Station({
    tableId: '2'
});

s.save(function(err) {

Result

{ "_id" : ObjectId("56e68bcf851a00680832ef13"), "tableId" : "2", "stations" : [ ], "__v" : 0 }

We know the default value of stations is empty array, which is design behavior of mongoose. The upsert: true will add one new document not for sub-document.

To insert station subdocument, we can first check whether the stopId exists, if not, insert new station subdocument. otherwise, we can insert new incoming subdocument into stations . Here are sample codes

Station
    .findOneAndUpdate({tableId: '2', 'stations.stopId': {$exists: false}}, 
                     {$addToSet: {stations: {stopId: '1234', incoming: []}}},
                   function (err, doc){
                        if (err)
                            console.log(err);
                        else{
                            Station
                                .findOneAndUpdate( 
                                  {'stations.stopId': 1234}, 
                                  {$addToSet: {'stations.$.incoming': {vehicleId: 22, timeAway: 400}}}, 
                                  function(err, doc) {
                                    if (err)
                                        console.log(err);
                                    else
                                        console.log(doc);
                                  });

                        }
                   });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM