4

I have document in record collection Mongodb (3.4) like below :-

    { 
      "_id" : ObjectId("592d0c78555a7436b0883960"), 
      "userid" : 7, 
       "addresses" : [
        {
            "apporx" : 50.0, 
            "loc" : [
                -73.98137109999999, 
                40.7476039
            ]
        }, 
        {
            "apporx" : 15.0, 
            "loc" : [
                -73.982002, 
                40.74767
            ]          
        }, 
        {
            "apporx" :10.0, 
            "loc" : [
                -73.9819567, 
                40.7471609
            ]
        }
     ]
    }
`

I created index on this collection using below query :- 
`db.records.createIndex({'addresses.loc':1})`

when i execute my below query :-
`db.records.aggregate( 
      {$geoNear : {
        near : [ -73.9815103, 40.7475731 ],
        distanceField: "distance" 
    }});

this result gives me distance field.now can you explain me in my document which address array in this multiple elements exists. how can i determine for which element this result true?

Another question :- if i make condition on "addresses.apporx" like greater then or equal then is there any way to find location of this condition?

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
5a01d01P
  • 663
  • 2
  • 9
  • 20

1 Answers1

3

Firstly I strongly advise that you create a "2dsphere" index for your collection if you intend to to geospatial queries on real world coordinates.

Make sure to drop other indexes you may have been playing with:

db.records.dropIndexes();
db.records.createIndex({ "addresses.loc": "2dsphere" })

In order to do what you want, first take a look at the slight modification that also includes the includeLocs option to $geoNear

db.records.aggregate([
  { "$geoNear": {
     "near": [ -73.9815103, 40.7475731 ],
     "spherical": true,
     "distanceField": "distance",
     "includeLocs": "locs"
  }}
])

Now you will see output that looks like this:

{
        "_id" : ObjectId("592d0c78555a7436b0883960"),
        "userid" : 7,
        "addresses" : [
                {
                        "apporx" : 50,
                        "loc" : [
                                -73.98137109999999,
                                40.7476039
                        ]
                },
                {
                        "apporx" : 15,
                        "loc" : [
                                -73.982002,
                                40.74767
                        ]
                },
                {
                        "apporx" : 10,
                        "loc" : [
                                -73.9819567,
                                40.7471609
                        ]
                }
        ],
        "distance" : 0.0000019174641401278624,
        "locs" : [
                -73.98137109999999,
                40.7476039
        ]
}

So what that returned was not only the distance to the point that was nearest but "which" location was the match used.

So if you wanted to $filter the original array to return the nearest, then you can:

db.records.aggregate([
  { "$geoNear": {
     "near": [ -73.9815103, 40.7475731 ],
     "spherical": true,
     "distanceField": "distance",
     "includeLocs": "locs"
  }},
  { "$addFields": {
    "addresses": {
      "$filter": {
        "input": "$addresses",
        "as": "address",
        "cond": { "$eq": [ "$$address.loc", "$locs" ] }
      }
    }
  }}
])

And that returns the array with only that match:

{
        "_id" : ObjectId("592d0c78555a7436b0883960"),
        "userid" : 7,
        "addresses" : [
                {
                        "apporx" : 50,
                        "loc" : [
                                -73.98137109999999,
                                40.7476039
                        ]
                }
        ],
        "distance" : 0.0000019174641401278624,
        "locs" : [
                -73.98137109999999,
                40.7476039
        ]
}
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • Thank you..My first question is solved.But my another question :- if i make condition on "addresses.apporx" like greater then or equal then is there any way to find location of this condition? – 5a01d01P May 31 '17 at 10:37
  • @SandipKumar Not sure what you mean and that might be a different question. But if you mean *"compare to the distanceField"* that is projected into the document, then much like above, add another pipeline stage to compare the two values. Play with `$project` and `$redact` for this, and read the documentation on "distanceField" from the `$geoNear` manual page. – Neil Lunn May 31 '17 at 10:44
  • @SandipKumar On that point of "distance". You are probably better off using the GeoJSON form than a legacy "array" form. The reason being is the "distance" returned from "legacy" is in **radians** and needs conversion to say kilometers. GeoJSON coordinates when used in comparison will consistently return the result by **meters**. So that is probably going to be more consistent with a "stored distance". – Neil Lunn May 31 '17 at 10:47
  • Is there any way in GeoJSON like my "array" form. And my question is :- In this array there are multiple elements so i have a key i.e. "apporx" . so first i want condition like "approx" between 50 and 70.so that distance will calculate between that elements.hope you got it. – 5a01d01P May 31 '17 at 10:53
  • @SandipKumar I'm really not sure I do understand what you mean here. If you mean doing something like setting a query condition with "apporx" between 12 and 20 so the second element of the array was only considered for nearest, then you cannot do that and arrays are not the best storage for that. If you mean obtain the nearest results and then simply "remove" any documents from results that did not have an array entry or "matching" array entry with a value in that range, then **yes** you can do that. This really would be better asked in a separate question. – Neil Lunn May 31 '17 at 11:09
  • Ok i will try to solve in another way . Thank You again. – 5a01d01P May 31 '17 at 11:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145542/discussion-between-sandip-kumar-and-neil-lunn). – 5a01d01P May 31 '17 at 11:15
  • Its returning only one location from the document, if there is another location which is also near to the point it ignored, what if i want multiple locations which is nearest to the given point. – Aakash Govardhane Feb 02 '23 at 10:05