2

I hope some one can help me - i want to populate a subdocument with a geo query to sort them:

i've got these models (simplified):

(a lot of articles):

   var articleSchema = mongoose.Schema({
      places: [{ type: mongoose.Schema.Types.ObjectId, ref: "places", required: false }],
      someData: { type: String, required: true },
})

(a lot of places):

var placeSchema = mongoose.Schema({
   longitudelatitude: {
      type: { type: String, required: true },
      coordinates: [
       { type: Number, required: true }, //longitude 
       { type: Number, required: true }  //latitude 
       ]},
   someData: { type: String, required: true }
})

my first query to find only places near a Position works fine:

getPlacesNearBy: function (lng, lat, skipNumber, limitNumber, callback) {
   Place.find({
     longitudelatitude: {
        $near: {
            $geometry: { type: "Point", coordinates: [lng, lat] },}}
        }, null, {skip: skipNumber, limit: limitNumber}, function (err, foundPlaces) {
            if (err)
                return callback(err, null);
            return callback(null, foundPlaces);
        })
    },

i get places near me - i can choose with limit how many - and i can reload some more with skip

now i wanted to do something similar:

i want to get an article - and populate the stored places (where you can get them) AND AFTER THAT i want to sort the places by distance and maybe to skip or limit the Response

so i tryed:

getPlacesforArticle: function (articleId, lng, lat, skipNumber, limitNumber, callback) {
    var projection = null;
    Article.findById(articleId, {places: 1}).populate("places", projection, {
        longitudelatitude: {
            $near: {
                $geometry: { type: "Point", coordinates: [lng, lat] },
            }
        }
    }, {skip: skipNumber, limit: limitNumber}).exec(function (getError, foundArticle) {
        if (getError)
             return callback(getError, null);
        callback(null, foundArticle.places);
        });
    }
},

So this query is working (throw no error) but it doesnt response what i want - i get places but they are "ordered" by database sequenze not by distance - so the $near seems to be ignored (tested without this query brings same result) but when i filter to some other content that works fine (like Name="test") also the limit is working but i cant skip some places of this response...

well i hope some one understand me and can help me =)!

thank you very much!

xyz-Mann
  • 51
  • 6
  • *"i get places but they are "ordered" by database sequence(sic) not by distance"* Well researched and actually was my suspicion on reading. At a guess I would say these are represented in exactly the order that the `ObjectId` values of the places array in the `Article` schema is. This really is not going to work for you, and the way I can think of to make it work most efficiently would be to store either the list of "articles" on the "places" entries, or alternately as a mapping in a separate collection. I could be done without data changes, but would be a very manual process. – Neil Lunn Jun 01 '17 at 08:14
  • well yes you're right the actual order is by the {ObjectId} but to store the articles in the places doesnt help - cause that are to many places :( to find the right would take to long or? - i cant query with near in a populated document? – xyz-Mann Jun 01 '17 at 08:26
  • It's expected. `.populate()` is not going to work for this. So you can either do the queries "manually" on the client ( which is basically what populate is doing ) and marry up the "ordered" results to the parents as you need. – Neil Lunn Jun 01 '17 at 08:31
  • **Or** you can use [`$lookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/) on the server. But of course the problem is the needed aggregation [`$geoNear`](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/) needs to be run directly on your "places" collection, and the `$lookup` needs data to relate back to "articles". Currently the references are in the wrong collection for that server operation to work. These are basically the decisions you need to make. – Neil Lunn Jun 01 '17 at 08:31
  • Ok when i understand you right i have only have different ways: 1.) calculate the distance manually on the found places (i have to Google how xD ) 2.) make $geoNear on place and search at each place for right article (but there are many places and one place got a lot of articles => query will take a long time) cause i definitely Need the places ordered by distance (so $lookup) doesnt help right? – xyz-Mann Jun 01 '17 at 08:47
  • It really does depend on what you actually need to do. You also clearly did not understand what I said in the comments and should probably do some more reading on those topics, including ["how populate actually works"](https://stackoverflow.com/questions/24096546/mongoose-populate-vs-object-nesting) which I summarize in that linked response. Whilst your question outlines the problem you have well, it unfortunately does not really describe the results that you really need to achieve. You could probably change some things to make presented solutions possible. – Neil Lunn Jun 01 '17 at 08:55

1 Answers1

1

So i've got a solution for my Problem...

https://docs.mongodb.com/manual/reference/command/geoNear/

use db.aggregate instead of db.find!

there you can define a seperate query =)

xyz-Mann
  • 51
  • 6