Location in mongoose, mongoDB - node.js

Whenever I try to store a location in my mongodb it doesn't show, so I guess I'm doing something wrong.
I can't find any documentation on how to store a location in mongoose so I'm just gonna ask it here.
I first create my model:
var eventSchema = mongoose.Schema({
name : String,
creator : String,
location : { type: [Number], index: '2dsphere'},
});
Then I try to add it to my database:
var newevent = new event({
name: name,
creator: tokenUser,
location : { type: "Point", coordinates: [longitude, latitude] },
});
When I look in my database everything is stored except the location ...

I fixed it myself.
I did this in my model:
loc : { type: {type:String}, coordinates: [Number]},
Underneath I made it a 2dsphere index.
eventSchema.index({loc: '2dsphere'});
And to add data to it:
loc: { type: "Point", coordinates: [ longitude, latitude ] },

Looks like your comment is correct (maybe), but the syntax for the index schemetype
here: http://mongoosejs.com/docs/api.html#schematype_SchemaType-index
It only accepts Object, Boolean, String
The correct syntax should be I think
var eventSchema = new Schema({
location: { type: [Number], index: { type: '2dsphere', sparse: true}}
)
based on the example in the docs.

This way i find it simpler.
const GeoSchema = mongoose.Schema({
type: {
type: String,
default: "Point",
},
coordinates: {
type: [Number], //the type is an array of numbers
index: "2dsphere"
}
})
const EventSchema = mongoose.Schema({
name: String,
creator: String,
location: GeoSchema
})
And when entering data
Event({
name,
creator,
location: { type: "point", coordinates: [longitude, latitude] }
})

Citing from the mongoose documentation for defining coordinates in schema, I'd like to make a tiny addition to #Laurenswuyts' answer for the 'type' property.
const exampleSchema = new mongoose.Schema({
location: {
type: {
type: String, // Don't do `{ location: { type: String } }`
enum: ['Point'], // 'location.type' must be 'Point'
required: true
},
coordinates: {
type: [Number],
required: true
}
}
});
Instead of leaving the 'type' property of 'location' open-ended with 'type: String', defining it with a single option enum 'Point' and setting 'required' to 'true' makes the code more robust. Then you would create index and add data the same way #Laurenswuyts did.

Related

Mongoose Geolocation set default coordinates

I am trying to create mongoose geolocation records with default coordinates. I am able to set the default values so it they are serialized, but they are not really committed to the database so geospatial queries won't work. Here is what I am doing (simplified)
const Place = new mongoose.Schema({
name: { type: String, required: true },
location: {
type: {
type: String,
enum: ['Point'],
required: true,
default: 'Point'
},
coordinates: {
type: [Number],
required: true,
default: function () {
return [0, 0] // Just 0, 0 for the example
}
}
}
When I pull up the record in the mongo shell, there is no location key at all.
i don't know more efficient way
but try this :
//pass data like this in your controller
Store.create({name, lat, lon})
make your model like this
const Place = new mongoose.Schema({
name: { type: String, required: true },
lat: { type: String},
lon: { type: String},
location: {
type: {
type: String,
enum: ['Point'],
},
coordinates: {
type: [Number],
index: '2dsphere'
}
}
// run before saving documents
Place.pre('save', function(next) {
this.location = {
type: 'Point',
coordinates: [this.lat, this.lon]
};
next();
});

How to add GeoJson data with mongoose?

I am sending the object to create a user model.
"{
type: 'Point',
coordinates: [ 25.2239771, 51.4993224 ]
}"
And, here is the Mongoose Schema that I created.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserProfileSchema = new Schema(
{
userId: {
type: String,
// required: true,
unique: true,
},
userFirstName: {
type: String,
// required: true,
},
userLastName: {
type: String,
// required: true,
},
userGender: {
type: String,
// required: true,
},
userCoordinates: {
type: {
type: String,
default: 'Point',
},
coordinates: {
type: [Number],
index: '2dsphere',
},
},
},
{ collection: 'userprofilemodels' }
);
module.exports = UserProfile = mongoose.model(
'userprofilemodels',
UserProfileSchema
);
This is the code that I am using to add geoJson type file. However, I am getting an error.
I also tried to add index after the Schema has been defined
await new userProfileModel({
userId,
userFirstName,
userLastName,
userCoordinates,
})
.save()
.then(() => {
console.log('it worked!');
res.send('worked!');
})
.catch((error) => {
console.log('did not worl')
// console.log(error);
});
If I exclude userCoordinates, then it works. So, def my geoJson object is wrong. However, I have no clue where I have made mistakes.
Mongoose supports GeoJSON objects indexing so first add the "2dsphere" index to the userCoordintes rather than to the coordinates within the object in order to make it work.
userCoordinates: {
type: {
type: String,
default: 'Point',
},
coordinates: {
type: [Number],
default: undefined,
required: true
},
index: '2dsphere'
},
Make sure your userCoordinates looks something like this:
const userCoordinates = {
type: "Point",
coordinates: [coordinatesA, coordinatesB],
};
Taken from the mongoose documentation it seems the GeoJSON Type mustn't be only a String.
here is the example with location as a GeoJSON type:
const citySchema = new mongoose.Schema({
name: String,
location: {
type: {
type: String, // Don't do `{ location: { type: String } }`
enum: ['Point'], // 'location.type' must be 'Point'
required: true
},
coordinates: {
type: [Number],
required: true
}
}
});

Mongoose giving error for NOT required Geo spatial field

I am using Mongoose Schema and simplified version looks like:
const newSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
location:{
type: {
type: String,
default: 'Point',
enum: ['Point']
},
coordinates: [Number],
}
});
const newModel = mongoose.model('NewModel', newSchema);
When I try to save a new document using this schema:
newModel.create({
"name": "Default name"
});
It is giving
error:
"Can't extract geo keys: { _id: ObjectId('5e8ed5ddf4781c24d0836b6e'), location: { type: \"Point\" },
name:\"Default name\"} Point must be an array or object"
However, when I fill the location field, it works well. I am wondering why Schema checking for the NOT required field.
var GeoJSON = require('mongoose-geojson-schema');
var mongoose = require('mongoose');
const newSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
location:mongoose.Schema.Types.GeoJSON
});
const newModel = mongoose.model('NewModel', newSchema);
and create data like:
newModel.create({
name: "Default name",
location: {
type: "Point",
coordinates: [longitude, latitude]
}
});
actually the problem occur due to you specified the default type is Point (that pushed by mongoose always if null or not specified) but you did't pass coordinates corresponding, and the point should be with coordinate

geo element must be an array or object: type: "Point"

When I tried post request like this
"{ "imgUrl": "Server\Pictures\i14182109167", "text": "Myself in
seoul", "tag": ["seoul", "tour"], "geometry" : {"type": "Point","coordinates": [80,
-27]} }"
The error causes
'Can\'t extract geo keys: { _id:
ObjectId(\'5b8e204455526366f86a6383\'), tag: [ "seoul", "tour" ],
date: new Date(1536041028423), imgUrl:
"Server\Pictures\i14182109167", text: "Myself in seoul", geometry: {
type: "Point", coordinates: [ 80, -27 ], _id:
ObjectId(\'5b8e204455526366f86a6384\') }, __v: 0 } geo element must
be an array or object: type: "Point"' }
even I added "type": "Point" in post request but, why?
const geoSchema = new Schema({
type: {
type: String,
default: 'Point',
index: '2dsphere'
},
coordinates: {
type: [Number]
}
});
const memoSchema = new Schema({
imgUrl: {
type: String
},
text: {
type: String
},
date: {
type: Date,
default: Date.now
},
tag: {
type: [String]
},
user: {
type: Schema.Types.ObjectId,
ref: 'Memo'
},
geometry: geoSchema
})
I experienced this error, tried several schema declarations, until I fixed by this implementing this design:
1. Create a new schema, which has Point as a property.
const mongoose = require('mongoose');
const {Point} = require('mongoose-geojson-schema');
const pointSchema = new mongoose.Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
2. Schema for the object including above as a property:
const itemsSchema = new mongoose.Schema({
description: {
type: String,
required: true
},
location: {
type: pointSchema,
required: true
}
)
const Item = mongoose.model('Item', ItemsSchema);
module.exports = Item;
enter code here
3. Finally, my controller succesfully instantiates the object like this:
var geolocation =
{
type: 'Point',
coordinates: [
lng,
lat
]
};
const item = new Item({
description: req.body.description,
location: geolocation
})
Hope that helps.
I changed geometry to loc it worked!
but, I don't know why...
I was facing the same issue even after doing everything mention here. After spending too much time on this problem I get to know that if we save a default value it will work correctly.
Just follow the above answer and add
location: {
type: pointSchema,
default: {
type: 'Point',
coordinates: [0, 0],
},
required: false,
},
And delete the previous documents if any document has location.

Mongoose, index locations array

I have an array of locations in a document and I want to add a 2dSpere index on that array. Is that possible?
var LocationSchema = new Schema({
type: { type: String, required: true },
geometry: {
type: { type: String, required: true },
coordinates: { type: Array, required: true}
},
properties: Schema.Types.Mixed
});
// Collection to hold users
var UserSchema = new Schema({
username: { type: String, required: true, unique: true },
locations: [LocationSchema]
},{
versionKey: false
}
);
How do I add a 2DSphere index on the geometry field in the locations array?
https://github.com/LearnBoost/mongoose/blob/master/examples/geospatial/geoJSONSchema.js#L19
LocationSchema.index({ 'geometry' : '2dsphere' });
If you store values for location as 2 numbers in array, then your index would look like:
coordinates: { type: [Number], index: '2dsphere', required: true }
Although you need to create such index in your database:
db.users.ensureIndex({ 'locations.geometry.coordinates': '2dsphere' });

Resources