简体   繁体   中英

mongoDB array inside document

When i update this data, the deslon and deslat part is not inserted in the document.

var locationData = { update_time: new Date() , 
                  location: [ 
                  {curlon: req.payload.loclon , curlat: req.payload.loclat},
                  {deslon: req.payload.deslon , deslat: req.payload.deslat}
                                   ]};

the update

userLocationModel.update({uid: req.params.accesskey}, locationData, { upsert: true }, function (err, numberAffected, raw) {
//DO SOMETHING
                });

I cannot understand why this is happining.

Here is the mongo document that gets inserted. The deslon and deslat are missing even if a new document is created.

{
  _id: ObjectId("52f876d7dbe6f9ea80344fd4"),
  location: [
    {
      curlon: 160,
      curlat: 160,
      _id: ObjectId("52f8788578aa340000e51673")
    },
    {
      _id: ObjectId("52f8788578aa340000e51672")
    }
  ],
  uid: "testuser6",
  update_time: ISODate("2014-02-10T06:58:13.790Z")
}

Also : Should I be using a structure like this if the document is updated frequently.

This is the mongoose model:

var userLocationSchema = mongoose.Schema({

    uid: String,                //same as the user access key
    update_time: Date,          //time stamp to validate, insert when updating. created by server.  

    location:[                
        {
            curlon: Number,         //current location in latitude and longitude <INDEX>
            curlat: Number
        },
        {
            deslon: Number,         //destination in latitude and longitude <INDEX>
            deslat: Number
        }
        ]
});

I wish to update both of the elemets. I don't wan't to insert a new one. But even when I update a non existent document(ie- which results in the creation of a new one), the deslon and deslat are missing.

I have a real problem with this structure but, oh well.

Your Schema is wrong for doing this. Hence also the superfluous _id entries. To do what you want you need something like this:

var currentSchema = mongoose.Schema({
  curlon: Number,
  curlat: Number
});

var destSchema = mongoose.Schema({
  destlon: Number,
  destlat: Number
});

var userLocationSchema = mongoose.Schema({

  uid: String,
  update_time: Date,

  location: [ ]

});

This is how mongoose expects you to do embedded documents. That will allow the update in your form you are using to work.

Also your logic on upsert is wrong as you have not included the new uid that is not found in the updated document part. You should take a look at $setOnInsert in the MongoDB documentation, or just live with updating it every time.

Actually, I'm just pointing you to how to separate the schema. As your usage in code stands location will accept anything by the above definition. See the mongoose docs on Embedded Documents for a more detailed usage.

This will work with your update statement as stands. However I would strongly urge you to re-think this schema structure, especially if you intend to do Geo-spatial work with the data. That's out of the scope of this question. Happy googling.

You have to tell mongo how to update your data. So add a simple $set to your update data:

var locationData = {
    $set: {
        update_time: new Date(), 
        location: [ 
            {curlon: req.payload.loclon , curlat: req.payload.loclat},
            {deslon: req.payload.deslon , deslat: req.payload.deslat}
        ]
    };

EDIT:

If you do not want to exchange the location property as a whole, but insert a new item into the array, use:

var locationData = {
    $set: {
        update_time: new Date() 
    },
    $push: {
        location: [ 
            {deslon: req.payload.deslon , deslat: req.payload.deslat}
        ]
    };

What you should consider is, if it is a good idea to put the current location and the destinations in one array, just because they have the same properties (lon/lat). If for example, there is always one current location and zero to many destinations, you could put the current location into a separate property.

To modify a specific location within an array, you can address it via.

var index = 2, // this is an example 
    arrayElement = 'location.' + n,
    locationData = { $set: {} };

locationData.$set[arrayElement] = {deslon: req.payload.deslon , deslat: req.payload.deslat};

userLocationModel.update({uid: req.params.accesskey}, locationData );

could it be that the intial collection was built with an other version of the schema? ie one that had only curlon and curlat? you may have to update the documents then to reflect the amended schema with the deslon and deslat properties.

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