Wednesday, November 11, 2020

MongoDB aggregate, unwind redact


Test data:

db.test.insert({ "locs" : [ 

{ "name" : "a", "address" : { "type" : "Point", "coordinates" : [ 0, 0 ] } }, 

{ "name" : "b", "address" : { "type" : "Point", "coordinates" : [ 1, 1 ] } }, 

{ "name" : "c", "address" : { "type" : "Point", "coordinates" : [ 2, 2 ] } }

]})


db.test.insert({ "locs" : [ 

{ "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } }

]})


db.test.ensureIndex( { "locs.address" : "2dsphere" } )



Query:


db.test.aggregate([

{ "$geoNear" : { near : { "type" : "Point", "coordinates" : [ 1, 1 ] }, distanceField: "dist.calculated", maxDistance: 5000, includeLocs: "dist.location", num: 5, limit: 200, spherical: true } },

{ "$unwind" : "$locs" },

{ "$redact" : { 

  "$cond" : { 

    if : { "$eq" : [ { "$cmp" : [ "$locs.address", "$dist.location" ] }, 0 ] },

    then : "$$KEEP", 

    else : "$$PRUNE"

   } 

 } 

}

])


The geoNear stage will output the entire documents with a "dist" field showing the distance and matching location field:


  "_id" : ObjectId("5786fa0ddeb382a191a43122"), 

  "locs" : [ { "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } } ],

  "dist" : { 

    "calculated" : 0, 

    "location" : { "type" : "Point", "coordinates" : [ 1, 1 ] }

  } 

}

We $unwind the "locs" array to allow for accessing individual array elements. The dist field is preserved.


The $redact field can then be used to remove any array elements where the address does not match the location returned by the $geoNear stage.


Results:


 "_id" : ObjectId("5786fa0ddeb382a191a43121"), 

 "locs" : { "name" : "b", "address" : { "type" : "Point", "coordinates" : [ 1, 1 ] } }, 

 "dist" : { "calculated" : 0, "location" : { "type" : "Point", "coordinates" : [ 1, 1 ] } } 

}

 "_id" : ObjectId("5786fa0ddeb382a191a43122"), 

 "locs" : { "name" : "h", "address" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } }, 

 "dist" : { "calculated" : 1574.1651198970692, "location" : { "type" : "Point", "coordinates" : [ 1.01, 1.01 ] } } 

}

references:

https://stackoverflow.com/questions/38339995/mongodb-geonear-with-multiple-matches-in-same-document




No comments:

Post a Comment