Mongoose setDefaultsOnInsert和2dsphere索引不起作用

时间:2015-06-28 14:28:07

标签: node.js mongodb mongoose 2dsphere

使用带有upsert的findOneAndUpdate并将setDefaultsOnInsert设置为true时,我在尝试在数据库中插入新用户时遇到问题。我要做的是设置以下架构的默认值:

var userSchema = new mongoose.Schema({
   activated: {type: Boolean, required: true, default: false},
   facebookId: {type: Number, required: true},
   creationDate: {type: Date, required: true, default: Date.now},
   location: {
       type: {type: String},
       coordinates: []
   },
   email: {type: String, required: true}
});

userSchema.index({location: '2dsphere'});

findOneAndUpdate代码:

model.user.user.findOneAndUpdate(
      {facebookId: request.params.facebookId},
      {
          $setOnInsert: {
              facebookId: request.params.facebookId,
              email: request.payload.email,
              location: {
                  type: 'Point',
                  coordinates: request.payload.location.coordinates
              }
          }
      },
      {upsert: true, new: true, setDefaultsOnInsert: true}, function (err, user) {
          if (err) {
              console.log(err);
              return reply(boom.badRequest(authError));
          }
          return reply(user);
      });

正如您所看到的,我还会存储用户的经度和纬度以及问题开始的位置。当findOneAndUpdate被调用时,我收到此错误:

{ [MongoError: exception: Cannot update 'location' and 'location.coordinates' at the same time]
name: 'MongoError',
message: 'exception: Cannot update \'location\' and \'location.coordinates\' at the same time',
errmsg: 'exception: Cannot update \'location\' and \'location.coordinates\' at the same time',
code: 16836,
ok: 0 }

当我删除2dsphere索引和所有与位置相关的代码时它确实设置了我的creationDate。我做错了什么?

2 个答案:

答案 0 :(得分:2)

setDefaultsOnInsert选项使用$setOnInsert运算符来执行其功能,看起来这与您自己使用$setOnInsert设置location相冲突。

解决方法是删除setDefaultsOnInsert选项并将其全部放在您自己的$setOnInsert运算符中:

model.user.user.findOneAndUpdate(
      {facebookId: request.params.facebookId},
      {
          $setOnInsert: {
              activated: false,
              creationDate: Date.now(),
              email: request.payload.email,
              location: {
                  type: 'Point',
                  coordinates: request.payload.location.coordinates
              }
          }
      },
      {upsert: true, new: true},
      function (err, user) {
          if (err) {
              console.log(err);
              return reply(boom.badRequest(authError));
          }
          return reply(user);
      });

答案 1 :(得分:0)

其中一个开发人员在github上回复了我的问题并将其作为4.0.8版本的里程碑添加,这是他的解决方法:

  $setOnInsert: {
          facebookId: request.params.facebookId,
          email: request.payload.email,
          'location.type': 'Point',
          'location.coordinates': request.payload.location.coordinates
  }

他的解决方案对我不起作用,我收到以下错误:

{ [MongoError: exception: insertDocument :: caused by :: 16755 Can't extract geo keys from object, malformed geometry?: { _id: ObjectId('559024a0395dd599468e4f41'), facebookId: 1.020272578180189e+16, location: { coordinates: [], type: "Point" }, email: "druwe.jeroen@gmail.com", gender: "male", lastName: "Druwé", firstName: "Jeroen", __v: 0, activated: false, creationDate: new Date(1435509921264), familyDetails: { children: [] } }]