The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

Jumy Elerossë (11) [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ë (11) [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 (7) [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.