Upexpaned更新:如何使用查找和更新MongoDB中另一个模式的数组

时间:2015-10-16 20:29:40

标签: mongodb mongoose

我有两个架构。一个是这样的。

var tripSchema = mongoose.Schema({

distance :{
    type: 'Number',
    required: true

},
source : {
     latitude: {
        type: 'Number',
        required: true
     },
    longitude: {
        type: 'Number',
        required: true  
    }
},
destination: {
     latitude: {
        type: 'Number',
        required: true
    },
    longitude: {
        type: 'Number',
        required: true  
    }
},
tripON:{
        type : 'Boolean',
        default: false
    }
}

和另一个这样的架构

var userTrips = mongoose.Schema({
    userId: {
        type: Schema.Types.ObjectId,
        required: true,
        ref : 'users'

    },
 trips : [tripSchema]
});

现在通过使用一些查询我已经创建了这样的文档。

"_id" : ObjectId("561bf7c0a3724f066b834985"),
    "userId" : ObjectId("561bda2117a4b49362b14dfb"),
    "deviceId" : "58",
    "carId" : "abcd123",
    "trips" : [
        {
            "startTime" : ISODate("2015-05-20T15:28:55Z"),
            "_id" : ObjectId("561ea4df42d8b60947a79b4b"),
            "tripON" : true,
            "source" : {
                "latitude" : 13.07,
                "longitude" : 77.6181319
            }
        }]

现在将tripON的值更改为false我写了这个查询并介意你我不想upsert但严格更新。

Trip.update({ userId: deviceUserCarMap.userId, deviceId: deviceId, carId: deviceUserCarMap.carId},
                        { $set: { 'trips.$.destination': { latitude: lat, longitude: lng }, 'trips.$.tripON': false} }, null,
                        function (err, trip) {
                            if (err) {
                                console.log(err);
                            }
                            else {
                                console.log('Trip End Saved');
                                userCache.toggleTripFlag(userIndex);
                                console.log(trip);
                            }
                        });

我得到一个错误。

[MongoError: The positional operator did not find the match needed from the query. Unexpanded update: trips.$.destination]
  name: 'MongoError',
  message: 'The positional operator did not find the match needed from the query. Unexpanded update: trips.$.destination',
  driver: true,
  index: 0,
  code: 16837,
  errmsg: 'The positional operator did not find the match needed from the query. Unexpanded update: trips.$.destination' }

我该如何解决? 编辑: 即使在提供此查询后:db.trips.findOne({'trips.0._id' : ObjectId("561ea4df42d8b60947a79b4b") })我在userTrips中获取tripSchema数组的所有元素,而不只是一个。为什么呢?

1 个答案:

答案 0 :(得分:0)

终于找到了答案......虽然不是全部。但这是来自评论中给出的链接的方法。

  

“$运算符可以更新匹配的第一个数组元素   使用$ elemMatch()运算符指定的多个查询条件。“

     

“与更新操作一起使用时,例如db.collection.update()和   db.collection.findAndModify(),位置$运算符充当a   与查询文档匹配的第一个元素的占位符。“

     

“位置$运算符不能用于遍历的查询   多个数组...因为$占位符的替换是   单个值“

所以你必须在MongoDB中编写一个脚本。现在该如何写。

  1. 在〜/ data / db文件夹中创建一个名为scripts的文件夹,然后创建一个myScript.js文件。
  2. 在那里写db = connect("localhost:27017/metaiot");
  3. 现在转到您的mongo shell并输入load(fullpath/data/db/scripts/myScript.js)。就我而言,它看起来像load("/home/oroborus/data/db/scripts/myScript.js")。如果成功加载将返回true。如果您收到错误,则表示您的文件路径错误。请提供完整的路径名称。即使mongo文档说相对路径工作也不要听。使用绝对路径。我通过反复试验发现了这一点。
  4. 现在写一个像这样的脚本是真的。它是对问题评论中给出的脚本的修改。为我量身定制。

  5. db = connect("localhost:27017/metaiot");
        var numbers = db.trips.find({trips :{$elemMatch : {"tripON":false}}});
        numbers.forEach(function(setter)
            { for(var index in setter.trips){
    
                print(setter.trips[index]._id)
            }
        });
    

    现在做你喜欢做的事。我花了3个小时来搞清楚这一点。但它是值得的。