2

Is it possible to query a collection in MongoDB and return the results grouped by geometric boundaries? For instance, I have one collection of addresses, each of which has a lat/long defined as a GeoJSON Point. I also have a collection of city council wards, each of which has a GeoJSON MultiPolygon object defining its boundaries. Is there a way to query the wards collection such that my results are populated with a field that shows the total number of addresses in each ward?

Conversely, is it possible to query the addresses collection and get my results populated with the ward that each address lies within?

I have read up on geoSpatial operators, the aggregation framework, and mapReduce functionality, but I just can't quite see how they would all go together in this particular instance.

Thanks!

Ben
  • 571
  • 2
  • 4
  • 15

2 Answers2

1

For the first question, I used $geoWithin operator. Knowing ward coordinates, you can build a query on addresses collection using $geoWithin, which works with multiPolygons.

db.addresses.find(
{
   addressCoordinates: {
      $geoWithin: {
          $geometry: {
             type: "MultiPolygon" ,
             coordinates: [ /*ward coordinates*/ ]
          }
      }
   }
});

http://docs.mongodb.org/manual/reference/operator/query/geoWithin/#op._S_geoWithin


For the second question, if wards and addresses are two separate collections without one-way or two-way reference to each other, then your're talking about table joins, which is not supported in mongoDB. And the only way I can think of is to do it in your code, correct me if I am wrong.

Another solution would be to restructure your ward or addresses collection schema, so that one has a reference to another. Address example:

{
    "name": "Trafalgar square",
    "coordinates": [/*your coordinates*/],
    "ward": ObjectId("5fbd....") // ward's ObjectID
}
AzaFromKaza
  • 768
  • 1
  • 10
  • 24
  • Thanks. I actually ended up going the other way and making an array of address objectIds on the ward document. It worked better for my particular requirements. – Ben Feb 05 '15 at 02:28
1

as pointed out, it sounds like a join is needed but not possible with our friend mongo. however, mongos ease of creating (and throwing away) tables/collections is ideal for making temporary (or perm) olap tables that then suit final query purposes. opposed to restructuring the collection schema that may already match the initial business case. check out joining 2 collections as a start. you can use crap-reduce or mongo shell scripts to build those olap collections. both methods are slow and not intended for justintime analytics. i would also look at this post about 20x perf.

Community
  • 1
  • 1
Gabe Rainbow
  • 3,658
  • 4
  • 32
  • 42
  • Thanks for the thorough response. Aza's solution ended up being appropriate for me so I accepted that one, but I voted yours up. – Ben Feb 05 '15 at 02:29