I have the following "query":
MySchema
.where('address1.loc').near({
center: {
type: 'Point',
coordinates: user.address1.loc
},
maxDistance: 10 * 1000
}).where('address2.loc').near({
center: {
type: 'Point',
coordinates: user.address2.loc
},
maxDistance: 10 * 1000
})
.exec(function(err, objects) {
console.log(err);
console.log(objects);
if(err) return eachCallback(err);
return eachCallback();
});
My schema has two addresses (one pickup- and one handover-address). So I have to use two "nears". But this doesn't seem to be possible:
{ [MongoError: Can't canonicalize query: BadValue Too many geoNear expressions] name: 'MongoError' }
What are my alternatives?
Update:
I talked to some guys from MongoDB. Although my use case for this is valid, this doesn't seem to be possible out-of-the-box. So I'm looking for a "workaround". If you need details about the use case, let me know.
And here is how I defined the location inside my "addresses":
...
loc: {type: [Number], index: '2dsphere'},
...
I had encountered the same issue and error message. But I cannot remember exactly how I could overcome. I hope we can overcome your issue!
If your schema definition like the following, please try to the below solution;
loc : {
'type': { type: String, default: 'Point' },
coordinates: [Number]
}
Could you check address.loc.coordinates stores as number on your collection?
Alternate way
Try to use $geoWithin operator
I think you can change your questioning clauses like the following. You should use $geoWithin and $centerSphere instead of $near and $maxDistance. You've tried to find records that have loc fields in 10.000 meters proximity. $centerSphere indicates radius, it uses legacy coordinate values (only [longitude, latitude]) and it can used with geoJSON field and 2dsphere index. And your $centerSphere definition must be 10/6371 for 10 km. (tutorial).
If you use a second operator with $near operator it occurs a problem on MongoDB side.
You cannot combine the $near operator, which requires a special geospatial index, with a query operator or command that uses a different type of special index. For example you cannot combine $near with the $text query.
var r = 10/6371;
var area1 = { center: address1.loc.coordinates, radius: r, unique: true }
var area2 = { center: address2.loc.coordinates, radius: r, unique: true }
MySchema
.where('address1.loc').
.within()
.circle(area1)
.where('address2.loc').
.within()
.circle(area2)
.exec(function(err, objects) {
console.log(err);
console.log(objects);
if(err) return eachCallback(err);
return eachCallback();
});
Hope this helps..
Related
I am using Node.JS, MongoDB and express.js. I keep coordinates in my database. And I want to get the coordinates to near me. How can I do it?
I thought about converting the meridians to km. I was able to calculate at the equator, but due to the shape of the earth, the distance between the meridian was not equal everywhere. I couldn't find any other solution.
My coordinate parameter in Mongo Model:
coordinate: {
type: String,
},
Example value:
coordinate: "41.08112226606513,29.066728949546814"
{
<location field>: {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ <longitude> , <latitude> ]
},
$maxDistance: <distance in meters>,
$minDistance: <distance in meters>
}
}
}
use this above query in your query
please read this above official document
I want to create a String + number every time a value is inserted on database (the number must be autoincrement).
Is it possible to do in Schema? Or do I need to do that before the value's inserted on database?
'question' -> String followed by an autoincrement number
var random = [{
question: 'question1'
},{
question: 'question2'
},{
question: 'question3'
},{
question: 'question4'
}];
const RandomSchema = new Schema({
question: {
type: String,
unique: true
}
})
Autoincrement fields in Mongodb, don't work exactly the same way that they do in an RDBMS. There is a lot more overhead involved. Never the less, creating an auto field is a solved problem. There is also a third party mongoose-autoincrement package that make it a lot easier.
Extending, from that. Your problem is a solved problem too. Because
the string part will always be the same
Simply use string concatenation to prepend 'question' to the auto increment field at display time.
Here is what I implemented with one of the approaches #e4c5 pointed out, without the use of a third-party package.
Define add.js as below:
db.counters.insert(
{
_id: "itemid",
seq: 0
}
)
function getNextSequence(id) {
var ret = db.counters.findAndModify(
{
query: { _id: id },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
db.randoms.insert(
{
question: "question"+getNextSequence("itemid"),
}
)
db.randoms.insert(
{
question: "question"+getNextSequence("itemid"),
}
)
After starting a mongod instance, do mongo < add.js.
I have a Node.js test in wich multiple Objects simulates to move away from some point in a map and Im countinuously testing if they´re within a radious from that point.
Each object corresponds to a Model with a nested legacy 2d Index 'location.loc'.
I have used this queries
var center={_lat:20,lng:-100};
var area = {
center: [center._lng,center._lat],
radius: 100,//This are supossed to be meters
unique: true,
spherical: true }
MyModel.where('location.loc')
.within()
.circle(area)
.exec(function (err, records) {
if (err) {
throw err;
}
//Log Length of records
});
And
MyModel.find({
"location.loc": {
$near: [center._lng,center._lat],
$maxDistance: 1 //This is suposed to be a mile
}
}).exec(function(err, documents) {
if (err) {
throw err;
}
//Log documents length
});
But both scripts returns me te entire collection of documents, even when they are miles away from the point.
At the same time im doing the same queries in my Mongo client with $near,$geoWithin and those queries gives me the right answer.
What is wrong with my Mongoose scripts?
Should only thest with within().circle() for this scenario?
Turn out that the radius in the first code are wrongly defined.
In this Mongo documentation says
With spherical: true, if you specify a GeoJSON point, MongoDB uses meters as the unit of measurement
But this is for a GeoJSON point and for geoNear.
For the legacy coordinate format [long,lat], we must divide the radius value in miles by 3963.2 to cast it as radians. See this Example.
I am trying to store some geojson points in mongo db.Here is the mongoose schema I have defined.
new mongoose.Schema({
itemName:String,
loc:{ type: [Number], index: '2dsphere'}
});
Next I am trying to run a near operator to find out some points nearby.This is how I have defined the near query.
Model.where('loc').near({ center: { type:"Point",coordinates: [10,10] }, maxDistance: 20 }).exec(function(err,data){
console.log(err);
if (!err && data) {
console.log("Success");
} else {
console.log("Error");
}
});
But this is returning an error value as follows:
{ [MongoError: Can't canonicalize query: BadValue geo near accepts
just one argu ment when querying for a GeoJSON point. Extra field
found: $maxDistance: 20] name : 'MongoError' }
If i remove the maxDistance it is returning all the collection elements.
Any idea why this error is coming?Thanks in advance for any help
Mongoose is still using the 'geoNear' database command form. This is considered obsolete in all ongoing versions of MongoDB.
Use the standard query form instead, which has been integrated with the standard query engine since MongoDB 2.6 and greater versions:
Model.find({
"loc": {
"$near": {
"$geometery": {
"type": "Point",
"coordinates": [ 10,10 ],
},
"$maxDistance": 20
}
}
},function(err,docs) {
// do something here
});
It's JavaScript, a "dynamically typed language". You don't need these ridiculous function helpers that are needed for strict typed languages with no dynamic constructs for defining and Object structure.
So do what the manual (which all examples are in JSON notation, which JavaScript natively understands) tells you to do and you are always fine.
I'm new to mongoDB and the usage of geoJSON within it.
I have the following schema I created using the mongoose module:
var mongoose = require('mongoose');
var hikeSchema = mongoose.Schema({
name: String,
area: String,
length: Number,
time: String,
Difficulty: { type : Number, min : 0 , max :5 },
start_coord: {
lon: Number,
lat: Number
},
rank_count: Number,
avg_overall_rating: { type : Number, min : 0 , max :5 },
completed_count: Number,
description: String,
ranking_pages: [
mongoose.Schema.Types.ObjectId
]
});
module.exports = mongoose.model('Hike', hikeSchema);
I used a simple Number type to represent to longitude and latitude inside a sub object within the schema.
I don't know if this is the way to go about it. I want it to be saved as a geoJSON object and then run queries on this object.
I recommand you to see the mongoDB part for geolocation datas : http://docs.mongodb.org/manual/core/2d/
To store longitude, latitude, MongoDB take you the correct data structure to save items :
To store location data as legacy coordinate pairs, use an array or an embedded document.
When possible, use the array format:
loc : [ < longitude > , < latitude > ]
Consider the embedded document form:
loc : { lng : , lat : }
Arrays are preferred as certain languages do not guarantee associative map ordering.
For all points, if you use longitude and latitude, store coordinates in longitude, latitude order.
On your shema, change
start_coord: {
lon: Number,
lat: Number
},
By :
start_coord: {
lng: Number,
lat: Number
},
Then you should add a 2dindex for your field start_coords to use all mongoDB geospatial queries :
db.collection.ensureIndex( { start_coord : "2d" } , { min : <l ower bound > , max : < upper bound > } )
EDIT It's important to set min and max if your longitude and latitude is not a real lng/lat (for example if you could use 2dindexes in a orthonormal map)
Now you can use all geospatial query operators : http://docs.mongodb.org/manual/reference/operator/query-geospatial/
You can also do it this way:
start_coord: {
type: [Number], // [<longitude>, <latitude>]
index: '2d' // create the geospatial index
}
Check this tutorial: How to use geospatial indexing in mongoDb