尝试使用GeoJson和$ near让玩家靠近用户使用位置,但是我没有从mongo获得索引设置错误,使用坐标设置为索引的mongoose。对于我见过的所有例子,代码看起来都是正确的。
我想要多个位置字段,所以使用$ near而不是GeoNear。
我从mongoDB获取错误
MongoError: can't find any special indices: 2d (needs index), 2dsphere (needs index), for: { location: { $near: { $geometry: { coordinates: [ 52, -0.4 ], type: "Point" }, $maxDistance: 10 } } }
玩家和用户模型
/** =========== Player Model =========== **/
var mongoose = require('mongoose');
var _ = require('underscore');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var geoJSONSchema = {
type: {
type: String,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates:{
type: mongoose.Schema.Types.Mixed,
index: '2dsphere',
default: [0,0]
}
};
.../\/\/\... other code .../\/\/\...
var playerSchema = new Schema({
created: { type: Date, default: Date.now },
controller_id: {
type: ObjectId,
required: true
},
controller: {
type: String,
required: true,
enum: ['ai', 'user'],
default: 'ai'
},
state:{
type: String,
required: true,
enum: ['survivor', 'zombie'],
default: 'survivor'
},
timestamps: {
created: { type: Date, default: Date.now },
last_active: { type: Date },
ai_last_spawned_at: { type: Date }
},
stats: playerStatsSchema,
profile: profileSchema,
location: geoJSONSchema,
//locations: geoJSONSchema, // Locations player has been
items: [{ type: Schema.Types.ObjectId, ref: 'items' }]
},{ collection : 'player' });
.../\/\/\... other code .../\/\/\...
playerSchema.pre('init', function (next) {
// do stuff
next();
});
// Compile Model
var Player = mongoose.model('Player', playerSchema);
/** =========== User Controller =========== **/
// Player is created with any new user, called inside another method.
var user = new User({
auth: options.auth,
contact: options.contact
}),
playerLocation = _.extend({ type: 'Point', coordinates: [0,0] }, options.location),
player = new Player({
controller_id: user._id,
controller: 'user',
state: 'survivor',
location: playerLocation,
//locations: playerLocation,
profile: {
name: (options.contact.first_name || '')
}
});
player.save(function (err, playerDoc) {
if (err) {
console.warn('[cUser:player.save]', err);
if (options.error) options.error(err);
return;
}
user.player_id = playerDoc._id;
user.player = playerDoc;
user.save(function (err, userDoc) {
if (err) {
console.error('[cUser:user.save]', err);
return;
}
if (options.success instanceof Function) options.success();
console.info('[cUser:user.save]created a new user (' + options.name + ') and player');
});
});
/** =========== Player GeoNear (User Method) =========== **/
userSchema.methods.getPlayersNear = function(distance){
if(!Player)Player = mongoose.model('Player');
return Player.find({ location: { $near: { $geometry: this.player.location , $maxDistance: distance||100 /* In Meters */ } }}, function(err,docs){
if(err) console.error('[mUser:player]',err);
return docs;
});
};
答案 0 :(得分:0)
这里的问题是您的索引是在错误的字段上定义的。你在这里真正做的是在"坐标"上定义索引。字段:
var geoSchema = {
"type": {
"type": String,
"enum": ["Point","LineString", "Polygon"],
"default": "Point"
},
"coordinates": {
"type": Schema.Types.Mixed,
"index": "2dsphere",
"default": [0,0]
}
};
你真正要做的是在"位置"上定义领域。这似乎很难做到" path"定义,但您也可以在"架构"上定义索引。所以作为一个最小的工作示例:
var async = require("async");
mongoose = require("mongoose"),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/geo');
var geoSchema = {
"type": {
"type": String,
"enum": ["Point","LineString", "Polygon"],
"default": "Point"
},
"coordinates": {
"type": Schema.Types.Mixed,
"default": [0,0]
}
};
var playerSchema = new Schema({
"name": String,
"location": geoSchema
});
playerSchema.index({ "location": "2dsphere"});
var Player = mongoose.model("Player", playerSchema, "player");
var player = new Player({
"name": "bill",
"location": {
"type": "Point",
"coordinates": [1,2]
}
});
async.series(
[
function(callback) {
player.save(function(err,player) {
if (err) throw err;
console.log(player);
callback();
});
},
function(callback) {
Player.find(
{
"location": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [1,2]
}
}
}
},
function(err,players) {
if (err) throw err;
console.log(players);
callback();
}
);
}
]
);
然后查询就可以了。
答案 1 :(得分:0)
"位置"对我来说不起作用,但是当我把它改成" loc"。
时它就起作用了