MongoDB's GeoJSON Object supporting a super set of geoJSON?

603 views
Skip to first unread message

孙逢

unread,
Apr 24, 2017, 8:21:52 PM4/24/17
to mongodb-user
Today, I upgraded my mongoDB version from 2.6 to 3.4, a unit test failed.
{ coordinates: { longitude, latitude }, type: 'Point' } should be an invalid geoJSON object.

I did some test with mongodb and I think it's a bug!

```
> db.devices.createIndex({ location: "2dsphere" })
{
       "createdCollectionAutomatically" : true,
       "numIndexesBefore" : 1,
       "numIndexesAfter" : 2,
       "ok" : 1
}


> db.devices.insert({ a: 1, location: { type: 'Point', coordinates: { longitude: 12, latitude: 3 } }})
WriteResult({ "nInserted" : 1 })

> db.devices.find()
{ "_id" : ObjectId("58fe6ffc810a8d6940f9f53c"), "a" : 1, "location" : { "type" : "Point", "coordinates" : { "longitude"
: 12, "latitude" : 3 } } }
```

Kevin Adistambha

unread,
Apr 30, 2017, 7:58:28 PM4/30/17
to mongodb-user

Hi,

{ coordinates: { longitude, latitude }, type: ‘Point’ } should be an invalid geoJSON object.

Thanks for reporting this! It is an issue, and we have opened https://jira.mongodb.org/browse/SERVER-29021 to track its progress. Please feel free to upvote/watch the ticket.

Best regards,
Kevin

Tim Huffam

unread,
Jun 20, 2017, 2:08:29 AM6/20/17
to mongodb-user
I have found a similar issue (maybe with the .Net driver) - when serializing a MongoDb GeoJSON Point object using the MongoDb.Net driver it yields the following invalid GeoJSON:
{ "coordinates":{ 
      "values":[-121.97620341421, 37.503287248864], 
      "longitude":-121.97620341421, 
      "latitude":37.503287248864 },
    "type":7, 
    "boundingBox":null, 
    "coordinateReferenceSystem":null, 
    "extraMembers":null 
}

This was for an object defined as:
public GeoJsonPoint<GeoJson2DGeographicCoordinates> location { get; set; }

I have checked with the GeoJSON spec, and this is definitely not valid (the coordinates property should contain an array).

Again, this could be an issue with the MongoDb.Net driver.
Regards
Tim

Kevin Adistambha

unread,
Jun 28, 2017, 2:10:17 AM6/28/17
to mongodb-user

Hi Tim

I have found a similar issue (maybe with the .Net driver) - when serializing a MongoDb GeoJSON Point object using the MongoDb.Net driver it yields the following invalid GeoJSON

I tried this code using the C# driver version 2.4.1:

using System;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.GeoJsonObjectModel;

namespace ConsoleApplication
{
    public class GeoDoc {
        public double Id {get; set;}
        public GeoJsonPoint<GeoJson2DGeographicCoordinates> loc {get; set;}
    }

    public class GeoTest {
        public static void Main(string[] args) {
            var client = new MongoClient("mongodb://localhost:27017");
            var collection = client.GetDatabase("test").GetCollection<GeoDoc>("geo");
            var doc = collection.Find(new BsonDocument{{"_id", 1}}).First();
            Console.WriteLine(doc.ToJson());
        }
    }
}

but haven’t been able to see the same result you do:

{ "_id" : 1.0, "loc" : { "type" : "Point", "coordinates" : [1.0, 2.0] } }

which is identical to the content of the collection:

> db.geo.find()
{ "_id": 1, "loc": { "type": "Point", "coordinates": [ 1, 2 ] } }

Could you post a compilable version of the code used, an example document from the collection, along with your MongoDB version and your C# driver version?

Best regards,
Kevin

Tim Huffam

unread,
Jun 30, 2017, 1:47:33 AM6/30/17
to mongodb-user
Interesting, yes when I try the same I get the correct results you get.Turns out it is the way asp.net (core) serializes the GeoJsonPoint<GeoJson2DGeographicCoordinates>  object.

Using your GeoDoc class, if I create a webapi controller with the following Get method:
public GeoDoc Get(int id){
return new GeoDoc(){Id = 1, loc = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(
new GeoJson2DGeographicCoordinates(-121.9, 37.5))};
}

This returns the following:
{"id":1.0,"loc":{"coordinates":{"values":[-121.9,37.5],"longitude":-121.9,"latitude":37.5},"type":7,"boundingBox":null,"coordinateReferenceSystem":null,"extraMembers":null}}

So it's nothing to do with MongoDb itself, but the serialisation (and by the looks of it, deserialisation) of the classes in the driver.  Although I'm not sure what is responsible for this (webapi/ASP.Net Core or the MongoDb.Driver class definition itself).

OOI, I've just tried using GeoJSON.Net, so updated the GeoDoc class like this:
public class GeoDoc
{
public double Id { get; set; }
//public GeoJsonPoint<GeoJson2DGeographicCoordinates> loc { get; set; }
public GeoJSON.Net.Geometry.Point loc { get; set; }
}
and with a webapi Get method of this:
[HttpGet("{id}")]
public GeoDoc Get(int id)
{
// return new GeoDoc(){Id = 1, loc = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(
// new GeoJson2DGeographicCoordinates(-121.9, 37.5))};
return new GeoDoc() { Id = 2, loc = new GeoJSON.Net.Geometry.Point(new GeoJSON.Net.Geometry.Position(32.816774, -96.770401)) };
}
It returns the following, correct GeoJSON:
{"id":2.0,"loc":{"coordinates":[-96.770401,32.816774],"type":"Point"}}

Unfortunately I have not been able to get GeoJSON.Net to work with MongoDB (using the MongoDb.Driver .Net driver)  - so it seems that GeoJSON operations are not yet possible for C# on MongoDb - which is a real shame.

Regards
Tim

Kevin Adistambha

unread,
Jul 6, 2017, 4:27:17 AM7/6/17
to mongodb-user

Hi Tim

I believe what you’re seeing is due to the mix between objects & the serializer used. As an example, I tried this code:

// GeoJSON.Net Point object
var Loc1 = new GeoJSON.Net.Geometry.Point(new GeoJSON.Net.Geometry.Position(1, 2));

// MongoDB GeoJsonPoint object
var Loc2 = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(new GeoJson2DGeographicCoordinates(1, 2));

// A: Serialize GeoJSON.Net Point object using MongoDB ToJson() method
Console.WriteLine("A: " + Loc1.ToJson());

// B: Serialize GeoJSON.Net Point object using Newtonsoft SerializeObject() method
Console.WriteLine("B: " + Newtonsoft.Json.JsonConvert.SerializeObject(Loc1));

// C: Serialize MongoDB GeoJsonPoint object using MongoDB ToJson() method
Console.WriteLine("C: " + Loc2.ToJson());

// D: Serialize MongoDB GeoJsonPoint object using Newtonsoft SerializeObject() method
Console.WriteLine("D: " + Newtonsoft.Json.JsonConvert.SerializeObject(Loc2));

and the resulting output is:

A: { "BoundingBoxes" : null, "CRS" : { "_t" : "DefaultCRS", "Properties" : { "name" : "urn:ogc:def:crs:OGC::CRS84" }, "Type" : 1 }, "Type" : 0, "Coordinates" : { "_t" : "Position", "Altitude" : null, "Latitude" : 1.0, "Longitude" : 2.0 } }

B: {"coordinates":[2.0,1.0],"type":"Point"}

C: { "type" : "Point", "coordinates" : [1.0, 2.0] }

D: {"Coordinates":{"Values":[1.0,2.0],"Longitude":1.0,"Latitude":2.0},"Type":7,"BoundingBox":null,"CoordinateReferenceSystem":null,"ExtraMembers":null}

Result marked “D” looks quite similar to the serialized output you have. This output is the result of MongoDB C# driver’s GeoJsonPoint object when serialized using Newtonsoft’s SerializeObject method (which appears to be GeoJSON.Net’s default serializer).

Note that outputs marked “A” and “D” are not canonical GeoJSON object according to RFC 7946, whereas “B” and “C” are correct GeoJSON objects.

I believe the mismatched object/serializer outputs the internal representation of the objects, instead of the correct GeoJSON object.

Also of note is GeoJSON.Net’s Latitude-Longitude coordinate order during object creation, which contrasts with the C# Driver’s Longitude-Latitude order. This results in the reversed coordinates in the “B” vs. “C” output above.

Best regards,
Kevin

Reply all
Reply to author
Forward
0 new messages