Jumy Elerossë (9) [Avatar] Offline
#1
Hi.

I'm having a problem in chapter 7. I'm even using the files from GitHub but the problem persists. When I open the home page, where all the locations should be listed, I have the API lookup error instead. Displaying in console the data causing the error 500, I get this:

GET /api/locations?lng=-0.7992599&lat=51.378091&maxDistance=20 500 172.504 ms - 3312
<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title></title><link rel="stylesheet" href="/stylesheets/bootstrap.min.css"><link rel="stylesheet" href="/stylesheets/font-awesome.min.css"><link rel="stylesheet" href="/stylesheets/tether.min.css"><link rel="stylesheet" href="/stylesheets/style.css"></head><body><nav class="navbar navbar-expand-lg navbar-dark bg-dark"><a class="navbar-brand" href="/">Loc8r</a><div class="container"><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarColor02"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="/about/">About</a></li></ul></div></div></nav><div class="container"><h1>Loc.geoNear is not a function</h1><h2></h2><pre>TypeError: Loc.geoNear is not a function


Therefore, the cause is something with geoNear. I spent hours and hours trying to sort this problem, but I only managed to have a huge headache. Does anyone has any idea what can be failing? I'm sure that the cause it's something simple and evident, but I can't find it.

Thanks for your help.
Jumy Elerossë (9) [Avatar] Offline
#2
Ok, it seems like the cause is mongoose's version. Using "mongoose": "^4.9.1" instead of "mongoose": "^5.0.1" (which is installed by default with Express at the moment of writing this) in package.json seems to solve the problem. I guess in the new version of mongoose geonear is used in a different way...
476453 (4) [Avatar] Offline
#3
So it happens they no longer support this method in latest Mongo/Mongoose.
geoNear

Model.geoNear() has been removed because the MongoDB driver no longer supports it

https://github.com/Automattic/mongoose/blob/d7364dc9cbe297ba04883db044bbd70ea53434a5/migrating_to_5.md#geonear

At first I was upset about the fact that we are being introduced to a date release of a library, but then I thought that it is not what the book is about. It is important to notice at the beginning of the book, though, that a certain version of mongoose is required. As far as I remember there is just a recommendation as for now.
331872 (131) [Avatar] Offline
#4
Hi, I'm Luis the editor of the book, I'll try to help answer this question.

First of thanks and apologize for the issue. Yes, I think since the focus is really the MEAN stack, possibly a Mongoose call is not the primary focus, as you said. The authors will either use a fixed version of the package that guarantees a working geoNear or possibly find a replacement for this. We'll make a note on this.

Thanks!
565611 (1) [Avatar] Offline
#5
Hello,
you can use the $geoNear aggregation in the api locations controller, it is supported without changes and be combined with other aggregations. The function "locationsListByDistance" looks then as follows (lines 18ff.)
Mitch

const locationsListByDistance = function (req, res) {
  const lng = parseFloat(req.query.lng);
  const lat = parseFloat(req.query.lat);
  const maxDistance = parseFloat(req.query.maxDistance);
  const point = {
    type: "Point",
    coordinates: [lng, lat]
  };
  if ((!lng && lng !==0 ) || (!lat && lat !== 0) || !maxDistance) {
    res
      .status(404)
      .json({
        message : 'lng, lat and maxDistance query parameters are all required'
      });
    return;
  }

  Loc
    .aggregate([{
      $geoNear: {
        near: point,
        maxDistance: maxDistance,
        key: "coords",
        distanceField: "distance",
        spherical: true,
        query: 'find( )'
      }
    }
  ])
    .limit(5)
    .exec((err, results) => {   // add error handling
      if (err) {
        res
          .status(400)
          .json(err);
      } else {
        res
          .status(200)  // 200: ok
          .json(results);
      }
  });
};
537960 (1) [Avatar] Offline
#6
Hi Luis.
Such a well developed book and thoroughly planned out. Many thanks to you, Simon and the team!

Mitch,
This is great, it totally worked. I updated the controllers/locations.js file with this code and now have a 'No Places Found Nearby' message, where as I had the 'API Lookup Error' before modifying.
Dan
331872 (131) [Avatar] Offline
#7
Glad you liked it. Thanks!
456502 (3) [Avatar] Offline
#8
My set geoNear like above, still doesn't work

and I try Mongo shell like , I got results, only one result, because I have one doc

>  db.locations.aggregate([{
... ... ...   $geoNear:{
... ... ...     near:{type: "Point", coordinates: [-0.96,51.45]},
... ... ...     spherical:true,
... ... ...     distanceField: "distance",
... ... ...     key:"coords",
... ... ...     maxDistance:20000,
... ... ...     query:'find()'
... ... ...   }
... ... ... }
... ... ... ])
{ "_id" : ObjectId("5b8a661b1029517e6e7e4c20"), "name" : "Starcups", "address" : "125 High Street, Reading, RG6 1PS", "rating" : 3, "facilities" : [ "Hot drinks", "Food", "Premium wifi"], "coords" : [ -0.9690884, 51.455041 ], "openingTimes" : [ { "days" : "Monday - Friday", "opening" : "7:00am", "closing" : "7:00pm", "closed" : false }, { "days" : "Saturday", "opening" : "8:00am", "closing" : "5:00pm", "closed" : false }, { "days" : "Sunday", "closed" : true } ], "reviews" : [ { "author" : "Simon Holmes", "_id" : ObjectId("5b8a9df71029517e6e7e4c21"),"rating" : 5, "timestamp" : ISODate("2017-03-11T16:00:00Z"), "reviewText" : "What a great place." } ], "distance" : 844.025373768282 }


but in app_api/controllers/location.js, I used same setting for geoNear
Loc
   .aggregate([{
                  $geoNear:{
                    near:point,
                    spherical:geoOptions.spherical,
                    distanceField: "distance",
                    key:"coords",
                    maxDistance:geoOptions.maxDistance,
                    query:'find()'
                  }
                }
    ])
   .limit(5)
   .exec((err,results,stats)=>{
        console.log("CP: "+results)
        if (err){
          res
            .status(400)
            .json(err)
        }else{
          const locations = _buildLocationList(req, res, results, stats);
          console.log('Geo Results', results);
          console.log('Geo stats', stats);
          res
            .status(200)
            .json(locations);
       }
    })


I got errors like:

[nodemon] starting `node ./bin/www`
Server listening on port 3000
Mongoose connected to mongodb://localhost/Loc8r
Mongoose: locations.ensureIndex({ coords: '2dsphere' }, { background: true })
(node:5451) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
lan  lat :-0.96  :51.378091
Mongoose: locations.aggregate([ { '$geoNear': { near: { type: 'Point', coordinates: [ -0.96,51.378091 ] }, spherical: true, distanceField: 'distance', key: 'coords', maxDistance: 20000, query: 'find()' } }, { '$limit': 5 } ], {})
CP: undefined
GET /api/locations?lng=-0.96&lat=51.378091&maxDistance=20000 400 71.249 ms - 88
GET / 304 2841.377 ms - -
GET /stylesheets/font-awesome.min.css 304 2.841 ms - -
GET /javascripts/bootstrap.min.js 304 3.197 ms - -
GET /stylesheets/bootstrap.min.css 304 58.210 ms - -
GET /javascripts/validation.js 304 11.591 ms - -
GET /stylesheets/style.css 304 58.282 ms - -
GET /stylesheets/bootstrap.min.css.map 404 89.073 ms - 3530



from
Mongoose: locations.aggregate([ { '$geoNear': { near: { type: 'Point', coordinates: [ -0.96,51.378091 ] }, spherical: true, distanceField: 'distance', key: 'coords', maxDistance: 20000, query: 'find()' } }, { '$limit': 5 } ], {})
, seems I got empty results,

but from
CP: undefined
, seems there are some error about pramas in "exec((err, results,stats)=> ...)



456502 (3) [Avatar] Offline
#9
follow above comment

I guess if there is some conflict between db.locations and app_api/model/ schema, because of
those document in db.locations seems did saved by app_api/model/location.js 's schema, so I checked as:

> db.locations.findOne({ _id: ObjectId("5b8a661b1029517e6e7e4c20") })
{
        "_id" : ObjectId("5b8a661b1029517e6e7e4c20"),
        "name" : "Starcups",
        "address" : "125 High Street, Reading, RG6 1PS",
        "rating" : 3,
        "facilities" : [
                "Hot drinks",
                "Food",
                "Premium wifi"
        ],
        "coords" : [
                -0.9690884,
                51.455041
        ],
        "openingTimes" : [
                {
                        "days" : "Monday - Friday",
                        "opening" : "7:00am",
                        "closing" : "7:00pm",
                        "closed" : false
                },
                {
                        "days" : "Saturday",
                        "opening" : "8:00am",
                        "closing" : "5:00pm",
                        "closed" : false
                },
                {
                        "days" : "Sunday",
                        "closed" : true
                }
        ],
        "reviews" : [
                {
                        "author" : "Simon Holmes",
                        "_id" : ObjectId("5b8a9df71029517e6e7e4c21"),
                        "rating" : 5,
                        "timestamp" : ISODate("2017-03-11T16:00:00Z"),
                        "reviewText" : "What a great place."
                }
        ]
}


it is fine, but didn't work by http://localhost:3000/api/locations/5b8a661b1029517e6e7e4c20 error as
Mongoose: locations.findOne({ _id: ObjectId("5b8a661b1029517e6e7e4c20") }, { fields: {} })
(node:5814) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
(node:5814) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
GET /api/locations/5b8a661b1029517e6e7e4c20 404 95.042 ms - 34


456502 (3) [Avatar] Offline
#10
I finally found reason for this issue.

I wrote some codes for create and save new location to loc8r database 's collection -- location,
this loc8r database already existed,after I tried many different way to find solution for above issue,
but I got error from Mongoose when I tried to save this new
location :
     Mongoose: locations.insertOne({ rating: 3, facilities: [ 'dumpling', 'cake', 'cunyua' ], _id: ObjectId("5ba5ec9c676dd63a032ad8d0"), name: 'penggang', address: '25 tiejie nanchang', coords: [ 0.71, 50.123 ], openingTimes: [ { _id: ObjectId("5ba5ec9c676dd63a032ad8d2"), days: 'Monday - Friday', opening: '9:00am', closing: '9:00pm', closed: false }, { _id: ObjectId("5ba5ec9c676dd63a032ad8d1"), days: 'Saturday', opening: '10:00am', closing: '10:00pm', closed: false } ], reviews: [], __v: 0 })
Inside api locationCreate controller
{ MongoError: db already exists with different case already have: [loc8r] trying to create [Loc8r]
    at Function.create (/Users/apple/Documents/xixijiu_ng-md/mean-server-client-with-ngcli6-aug-2018/node_modules/mongodb-core/lib/error.js:43:12)
    at toError (/Users/apple/Documents/xixijiu_ng-md/mean-server-client-with-ngcli6-aug-2018/node_modules/mongodb/lib/utils.js:149:22)
    at coll.s.topology.insert (/Users/apple/Documents/xixijiu_ng-md/mean-server-client-with-ngcli6-aug-2018/node_modules/mongodb/lib/operations/collection_ops.js:828:39)
    at /Users/apple/Documents/xixijiu_ng-md/mean-server-client-with-ngcli6-aug-2018/node_modules/mongodb-core/lib/connection/pool.js:531:18
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)
  driver: true,
  name: 'MongoError',
  index: 0,
  code: 13297,
  errmsg: 'db already exists with different case already have: [loc8r] trying to create [Loc8r]',
  [Symbol(mongoErrorContextSymbol)]: {} }


this error appeared in mongodb my database' name is "loc8r", but in my code is "Loc8r", that's
why I did any database caused error, so mongodb seems database name case-insensitive, but
can't have same name, both name is different case letter (Sorry for my english, I don't know
how to write this in english), and I hope you guys understand what i mean.