Gan*_*rey 2 geolocation mongoose mongodb geojson node.js
I am having great trouble with this. I am building a little API to get the closest stored elements (in a mlab MongoDB) given specific coordinates.
\n\nI want to get the closest elements from my DB using Mongo custom query tools like $near.
\n\nYou can find the original repo here!
\n\nThe original data is a little .csv that I converted to geojson format.
\n\nHere is a short version of that .csv:
\n\n\n\nHere is the geojson version of it:
\n\n{\n "type": "FeatureCollection",\n "features": [\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.4049238868200975, 48.82094216189432]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.3645320381923534, 48.816341825787724]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.3274838513968072, 48.86982967859056]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.23284629237154, 48.89111120713999]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.23284629237154, 48.89111120713999]\n },\n "properties": {\n "event_type": "click"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.4204737962258305, 48.85038737901075]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.4214870126092594, 48.86339618816508]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.4144620076022436, 48.876530301936576]\n },\n "properties": {\n "event_type": "imp"\n }\n },\n {\n "type": "Feature",\n "geometry": {\n "type": "Point",\n "coordinates": [2.2470618097659285, 48.88845096504584]\n },\n "properties": {\n "event_type": "imp"\n }\n }\n ]\n}\nRun Code Online (Sandbox Code Playgroud)\n\nHere is the schema using mongoose (as you can see, I did add 2dsphere index):
\n\nconst mongoose = require("mongoose");\n\nconst FeatureSchema = new mongoose.Schema({\n type: String,\n geometry: {\n type: { type: String, default: "Point" },\n coordinates: { type: [Number] }\n },\n properties: { event_type: String }\n});\n\nFeatureSchema.index({ geometry: "2dsphere" });\nconst MapEventSchema = new mongoose.Schema({\n type: String,\n features: [FeatureSchema]\n});\n\nconst MapEvent = mongoose.model("mapEvent", MapEventSchema);\n\nmodule.exports = MapEvent;\nRun Code Online (Sandbox Code Playgroud)\n\nHere is now the test (with Mocha) that I am struggling with:
\n\nconst assert = require("assert");\nconst MapEvent = require("../src/models/mapEvents");\nconst fs = require("fs");\n\ndescribe("Read test", () => {\n // create new room collection because collection is drop between each file\n beforeEach(done => {\n rawJSON = fs.readFileSync("./src/assets/test_assets/read_test.json");\n const parsedContent = JSON.parse(rawJSON);\n const mapEvent = new MapEvent(parsedContent);\n mapEvent\n .save()\n .then(() => {\n done();\n })\n .catch(error => {\n console.error(error);\n });\n });\n\n it("Find nearest event by coordonates", done => {\n const distance = 1000;\n const lat = 48.86;\n const lon = 2.35;\n\n function waitForIndex() {\n return new Promise((resolve, reject) => {\n MapEvent.on("index", error => (error ? reject(error) : resolve()));\n });\n }\n\n MapEvent.findOne({\n geometry: {\n $near: [lat, lon],\n $maxDistance: distance\n }\n })\n //.then(waitForIndex)\n .then(MapEvent.init())\n .then(nearestResult => {\n console.log("------------");\n console.log(nearestResult);\n console.log("------E-----");\n assert(nearestResult);\n done();\n })\n .catch(error => {\n console.error("************");\n console.error(error);\n console.error("******E*****");\n });\n });\n}); \nRun Code Online (Sandbox Code Playgroud)\n\nAs you may notice, I commented out waitForIndex() (find on a related Stackoverflow question) to use MapEvent.init() instead (find on github). Unfortunately, both solutions give me the same error output.
\n\nConnection is established\n Create test\n(node:12483) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.\n \xe2\x9c\x93 MapEvent saving\n\n Read test\n************\n{ MongoError: error processing query: ns=babylon_ad_db.mapevents batchSize=1 limit=1Tree: GEONEAR field=geometry maxdist=1000 isNearSphere=0\nSort: {}\nProj: {}\n planner returned error: unable to find index for $geoNear query\n at queryCallback (/home/geoffrey/babylon-ad/node_modules/mongodb-core/lib/cursor.js:248:25)\n at /home/geoffrey/babylon-ad/node_modules/mongodb-core/lib/connection/pool.js:532:18\n at process._tickCallback (internal/process/next_tick.js:61:11)\n ok: 0,\n errmsg:\n \'error processing query: ns=babylon_ad_db.mapevents batchSize=1 limit=1Tree: GEONEAR field=geometry maxdist=1000 isNearSphere=0\\nSort: {}\\nProj: {}\\n planner returned error: unable to find index for $geoNear query\',\n code: 2,\n codeName: \'BadValue\',\n operationTime:\n Timestamp { _bsontype: \'Timestamp\', low_: 7, high_: 1536667477 },\n \'$clusterTime\':\n { clusterTime:\n Timestamp { _bsontype: \'Timestamp\', low_: 7, high_: 1536667477 },\n signature: { hash: [Binary], keyId: [Long] } },\n name: \'MongoError\',\n [Symbol(mongoErrorContextSymbol)]: {} }\n******E*****\n 1) Find nearest event by coordonates\n\n\n 1 passing (3s)\n 1 failing\n\n 1) Read test\n Find nearest event by coordonates:\n Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/geoffrey/babylon-ad/test/read_test.js)\nRun Code Online (Sandbox Code Playgroud)\n\n我已经做了一些谷歌搜索,这就是我听说 $near 和 2dsphere 索引的方式。但我仍然不明白为什么它说找不到索引。即使我用 waitForIndex() 或 MapEvent.init() 等待它。
\n\n这个社区创造了一些很酷的奇迹,我希望你能帮助我。
\n\n谢谢,
\n此类错误表明索引未创建。通常这是由于坐标数据无效造成的。也许加载您的 mongo shell 并确保您的索引存在:
mongo
use yourdatabasename
db.yourcollection.getIndexes()
Run Code Online (Sandbox Code Playgroud)
你最终应该得到类似的结果:
{
"v" : 2,
"key" : {
"geometry" : "2dsphere"
},
"name" : "geometry_2dsphere",
"ns" : "databasename.yourcollection",
"2dsphereIndexVersion" : 3
}
Run Code Online (Sandbox Code Playgroud)
如果不存在,请尝试在 shell 中创建索引 - 如果无法创建索引,则会抛出错误:
db.yourcollection.createIndex( { geometry : "2dsphere" } )
Run Code Online (Sandbox Code Playgroud)