mongoDB数组里面的文件

时间:2014-02-10 07:04:37

标签: javascript node.js mongodb mongoose

当我更新此数据时,deslondeslat部分未插入文档中。

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

更新

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

我无法理解为什么这是幸福的。

这是插入的mongo文档。即使创建了新文档,也会遗漏deslondeslat

{
  _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")
}

另外:如果文档经常更新,我是否应该使用这样的结构。

这是猫鼬模型:

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
        }
        ]
});

我希望更新这两个元素。我不想插入一个新的。但即使我更新了一个不存在的文件(即导致创建一个新文件),deslon和deslat也会丢失。

3 个答案:

答案 0 :(得分:2)

我对这个结构有一个真正的问题但是,哦,好吧。

这样做你的架构是错误的。因此也是多余的_id条目。要做你想做的事,你需要这样的东西:

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: [ ]

});

这就是mongoose希望你做嵌入式文档的方式。这将允许您正在使用的表单中进行更新。

此外,upsert上的逻辑错误,因为您未包含更新文档部分中未找到的 uid。您应该查看MongoDB文档中的$setOnInsert,或者每次都更新它。

实际上,我只是指出如何分离架构。根据您在代码中的使用情况location将通过上述定义接受任何。有关更详细的用法,请参阅Embedded Documents上的mongoose文档。

这将与您的更新声明一起使用。但是,我强烈建议您重新考虑这种模式结构,特别是如果您打算对数据进行地理空间工作。这超出了这个问题的范围。快乐的谷歌搜索。

答案 1 :(得分:1)

您必须告诉mongo 如何更新您的数据。因此,在您的更新数据中添加一个简单的$set

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

修改

如果您不想整体更换location属性,但是在数组中插入新项目,请使用:

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

你应该考虑的是,如果将当前位置和目的地放在一个数组中是个好主意,只是因为它们具有相同的属性(lon / lat)。例如,如果总是一个当前位置和零到多个目的地,则可以将当前位置放入单独的属性中。

要修改数组中的特定位置,您可以通过。

进行处理
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 );

答案 2 :(得分:0)

可能是初始集合是使用其他版本的模式构建的吗?即一个只有curlon和curlat?您可能必须更新文档然后反映修改后的模式与deslon和deslat属性。