0

I have a complex geojson document stored in my MongoDB. My goal is to retrieve the objects that apply to my condition e.g:

I want to retrieve the objects that contain "avenue" in the 'features.properties.name'field. I have tried this: db.LineString.find({'features.properties.name' : "Avenue"}) which results:

enter image description here

As you can see, this returns the entire document. My goal is just to return the objects like the highlighted object 0 which fulfil the given condition. Also, could the results be visualized somehow?

Community
  • 1
  • 1
Menelaos Kotsollaris
  • 5,776
  • 9
  • 54
  • 68
  • @JohnnyHK *both $elemMatch and $ only return the first match*. Do you have any solution for returning **all** the matches? – Menelaos Kotsollaris Oct 22 '15 at 17:22
  • See the couple of answers to that question that use `aggregate` if you want all the matches. – JohnnyHK Oct 22 '15 at 17:29
  • @JohnnyHK Thank you very much. I will do more research to it... Do you know by any chance if I could extract the resulting document into GeoJSON format? It seems I can generate a `JSON` document but not a `GeoJSON` one.. – Menelaos Kotsollaris Oct 22 '15 at 18:22

2 Answers2

0
find(arg1)

command you use returns with documents stored in collection, so it can search nested docs, but cannot return part of top level collection document. It returns all document.

If your docs structure regular try to use this

find(arg1, arg2)

instead to limit returned fields https://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/

if your documents structure irregular, write a script with your favorite programming language

P_M
  • 2,723
  • 4
  • 29
  • 62
0

After much research, I found a way of actually querying specific objects and visualizing them using RoboMongo and Google Drag and Drop GeoJSON.

For the query part we can use the below technique as specified here:

//[Thematic]  Finds all the LineString documents that contain “Avenue” in their name.
db.LineString.aggregate(
 { $match : {
     "features.properties.name": /avenue/i
  }},
  { $unwind : "$features" },
  { $match : {
     "features.properties.name": /avenue/i
  }}
)

Here we use the $unwind aggregation stage in order to define what field we want to retrieve. After that we use $match in order retrieve the documents with the specific conditions. Note that the first match can take advantage of an index (Text, Spatial etc..) and fasten the time by a lot. By right clicking on the document in MongoDB we can view+store the generated JSON.

However, when working with Spatial data you will probably like to have your data in the map, especially when working with complex structures. In order to do so, you will need to convert your data from JSON to GeoJSON. Below I will show the regular expression I used in order to convert my file.

Algorithm JSON file (generated from MongoDB) to GeoJSON:

  1. Erase: "features" : \{.* AND "coordinates"[^}]*\K\} AND "type" : "Feature" AND "ok" : 1.0000000000000000 AND "id".*, **AND**"_id" : ObjectId(.*`
  2. Replace: "type" : "FeatureCollection",[^}]*\}, WITH "type" : "Feature", AND "result" : [ WITH "features" : [ { "type": "FeatureCollection", "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, "features" : [

I run these regular expressions using Notepad++:

  1. "features" : \{.*|"coordinates"[^}]*\K\}|"type" : "Feature"|"ok" : 1.0000000000000000|"id".*,|"_id" : ObjectId\(.*,
  2. "type" : "FeatureCollection",[^}]*\}, replace with "type" : "Feature",

Disclaimer: Please notice that your file might follow a different structure, since the way you project the data obviously effects the output file. In such a case, extra modification is required.

Now that we have the GeoJSON file we can drag and drop it to Google's GeoJSON API. The above query will give us the roads of Vancouver that contain "Avenue" on their names:

enter image description here

Thoughts: I believe that this job could be done directly from RoboMongo since the produced JSON can be converted to GeoJSON with some inferior changes. Also please note that this REGEX is way too complicated and if you are interested in a more stable solution I would suggest you to use a JSON Library like NodeJS, Jackson etc and generate a brand new file.I came up with this solution and it worked perfectly for my case.

Enjoy :)

Community
  • 1
  • 1
Menelaos Kotsollaris
  • 5,776
  • 9
  • 54
  • 68