在mongoose模式上应用2dsphere索引会强制要求使用位置字段吗?

时间:2013-05-05 20:29:41

标签: node.js mongodb mongoose

我有一个mongoose模式和模型定义如下:

var mongoose = require('mongoose')
  , Schema = new mongoose.Schema({
      email: {
        index: {
          sparse: true,
          unique: true
        },
        lowercase: true,
        required: true,
        trim: true,
        type: String
      },
      location: {
        index: '2dsphere',
        type: [Number]
      }
    })
  , User = module.exports = mongoose.model('User', Schema);

如果我尝试:

var user = new User({ email: 'user@example.com' });

user.save(function(err) {
  if (err) return done(err);

  should.not.exist(err);
  done();
});

我收到错误消息:

MongoError: Can't extract geo keys from object, malformed geometry?:{}

尽管此模式中的位置字段不是必需的,但无论如何它似乎都是这样的。我已经尝试添加default: [0,0],它确实绕过了这个错误,但是它似乎有点像黑客,因为这显然不是一个好的默认值,理想情况下,架构不需要用户始终拥有一个位置

使用MongoDB / mongoose的地理空间索引是否意味着需要索引的字段?

4 个答案:

答案 0 :(得分:38)

对于mongoose 3.8.12,您可以设置默认值:

var UserSchema = new Schema({
  location: {
    type: {
      type: String,
      enum: ['Point'],
      default: 'Point',
    },
    coordinates: {
      type: [Number],
      default: [0, 0],
    }
  }
});

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

答案 1 :(得分:17)

默认情况下,声明为数组的属性会接收要使用的默认空数组。 MongoDB已经开始验证geojson字段并对空数组大喊大叫。解决方法是在架构中添加一个预保存挂钩,以检查此场景并首先修复文档。

schema.pre('save', function (next) {
  if (this.isNew && Array.isArray(this.location) && 0 === this.location.length) {
    this.location = undefined;
  }
  next();
})

答案 2 :(得分:0)

我解决此问题的唯一方法是将索引类型从

更改
GEO:{
    type: [Number],
    index: '2dsphere'
}

GEO:{
    type: [Number],
    index: '2d'
}

那是一场噩梦

答案 3 :(得分:0)

使用地理位置创建架构并运行geospartial查询的正确方法是

    var UserSchema = new Schema({
  location: {
    type: {
      type: String,
      default: 'Point',
    },
    coordinates: {
      type: [Number]
    }
  }
});

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

并且当您开始节点项目时,请不要忘记将索引创建为

YourScema.createIndexes();
  

请注意,这很重要,因为索引2dsphere在   location.coordinates,如果您想运行geospartial查询!