Storage and operations of spatial data in MongoDB

Source: Internet
Author: User
In this example, we use the official C # Driver to store and query spatial data (vectors) in MongoDB) read vector element space information and attribute tables, and write them to MongoDB. Read the shapefile file and convert the space information to json using the Ogr library. [csh

In this example, we use the official C # Driver to store and query spatial data (vectors) in MongoDB) read vector element space information and attribute tables, and write them to MongoDB. Read the shapefile file and convert the space information to json using the Ogr library. [csh

This article uses the official C # Driver to store and query spatial data (vectors) in MongoDB)

Storage of Spatial Data

In this example, the vector element space information and Attribute Table are read from a Vector file (shapefile format) and written to MongoDB, the function of reading the shapefile and converting the space information into json is implemented through the Ogr library.

[Csharp] view plaincopyprint? 01. // open the Collection of MongoDB
02. Relational Database db = server. GetDatabase ("aa ");
03. Collect collection colSheng = db. GetCollection ("sheng ");
04. // use the Ogr library to open the Shapefile File
05. DataSource ds = Ogr. Open (@ "c: \ temp \ sheng. shp", 0 );
06. Layer lyr = ds. GetLayerByIndex (0 );
07. // Number of read elements and field count
08. int feaCount = lyr. GetFeatureCount (0 );
09. int fieldCount = lyr. GetLayerDefn (). GetFieldCount ();
10. // read all field names
11. List FieldNames = new List ();
12. for (int I = 0; I <fieldCount; I ++)
13 .{
14. fieldNames. Add (lyr. GetLayerDefn (). GetFieldDefn (I). GetName ());
15 .}
16. // Add all elements to MongoDB cyclically
17. for (int I = 0; I <feaCount; I ++)
18 .{
19. // use the Ogr library to convert the space information of vector elements into Json format
20. Feature fea = lyr. GetFeature (I );
21. Geometry geo = fea. GetGeometryRef ();
22. string json = geo. ExportToJson (null );
23.
24. BsonDocument doc = new BsonDocument ();
25.
26. // Save the space information in Json format to the Collection.
27. // BsonValue bs = BsonValue. Create (json); // This method is not allowed. After it is added to the library, it cannot be queried using a space query statement.
28. BsonValue bs2 = BsonDocument. Parse (json); // This method is correct.
29. // doc. Add (new BsonElement ("geom", bs ));
30. doc. Add (new BsonElement ("geo", bs2 ));
31. // store the attribute information of all fields in the Collection through Loops
32. for (int j = 0; j <fieldCount; j ++)
33 .{
34. string tmpFieldVal = fea. GetFieldAsString (j );
35. doc. Add (new BsonElement (fieldNames [j], tmpFieldVal ));
36 .}
37. var res = colSheng. Insert (Doc );
38 .}
// Open the Collection of MongoDB
Relational Database db = server. GetDatabase ("aa ");
Repeated collection colSheng = db. GetCollection ("sheng ");
// Use the Ogr library to open the Shapefile
DataSource ds = Ogr. Open (@ "c: \ temp \ sheng. shp", 0 );
Layer lyr = ds. GetLayerByIndex (0 );
// Read element quantity and field quantity
Int feaCount = lyr. GetFeatureCount (0 );
Int fieldCount = lyr. GetLayerDefn (). GetFieldCount ();
// Read all field names
List FieldNames = new List ();
For (int I = 0; I <fieldCount; I ++)
{
FieldNames. Add (lyr. GetLayerDefn (). GetFieldDefn (I). GetName ());
}
// Add all elements to MongoDB cyclically
For (int I = 0; I <feaCount; I ++)
{
// Use the Ogr library to convert the space information of vector elements to Json format
Feature fea = lyr. GetFeature (I );
Geometry geo = fea. GetGeometryRef ();
String json = geo. ExportToJson (null );

BsonDocument doc = new BsonDocument ();

// Save the space information in Json format to the Collection.
// BsonValue bs = BsonValue. Create (json); // This method is not allowed. After being added to the library, it cannot be queried using a space query statement.
BsonValue bs2 = BsonDocument. Parse (json); // This method is correct.
// Doc. Add (new BsonElement ("geom", bs ));
Doc. Add (new BsonElement ("geo", bs2 ));
// Store the attribute information of all fields in the Collection through Loops
For (int j = 0; j <fieldCount; j ++)
{
String tmpFieldVal = fea. GetFieldAsString (j );
Doc. Add (new BsonElement (fieldNames [j], tmpFieldVal ));
}
Var res = colSheng. Insert (Doc );
}

Then, you can view the vector data stored in MongoDB.

Enter:
[Csharp] view plaincopyprint? 01.> db. sheng. find (). limit (1)
> Db. sheng. find (). limit (1)

Result:
[Javascript] view plaincopyprint? 01. {"_ id": ObjectId ("5371bf4e1dbba31914224563"), "geo": {"type": "Polygon", "coordinates": [[89.8496, 14.093], [90.3933, 14.004], [90.2708, 13.4708], [89.7284, 13.5597], [89.8496, 14.093]}, "pyname": "sx", "boxtype ": "inter", "date": "Maid 12:41:42 "}
{"_ Id": ObjectId ("5371bf4e1dbba31914224563"), "geo": {"type": "Polygon", "coordinates": [[89.8496, 14.093], [90.3933, 14.004], [90.2708, 13.4708], [89.7284, 13.5597], [89.8496, 14.093]}, "pyname": "sx", "boxtype ": "inter", "date": "Maid 12:41:42 "}

The Field named geo is displayed, and the coordinates of the vector elements are stored in the Field.

Spatial Query and spatial index

Available space operations include geointersect, geowithin, near and so on, refer to http://docs.mongodb.org/manual/reference/operator/query-geospatial/
Here, geointersect is used as an example to describe:

[Csharp] view plaincopyprint? 01. // get Collection
02. Relational Database db = server. GetDatabase ("aa ");
03. Collect collection colSheng = db. GetCollection ("sheng ");
04.
05. // define a query box or query a polygon
06. var poly = GeoJson. Polygon (
07. GeoJson. Position (100, 20 ),
08. GeoJson. Position (110, 20 ),
09. GeoJson. Position (110, 40 ),
10. GeoJson. Position (100, 40 ),
11. GeoJson. Position (100, 20 ));
12. // define a query statement based on the query Polygon
13. var queryFilter2 = Query. GeoIntersects ("geo", poly );
14. // query and export cursor
15. cur = colSheng. FindAs (QueryFilter2). SetFields ("pyname", "date ");
16. // obtain the result
17. var res = cur. ToArray ();
18. for (int I = 0; I <res. Count (); I ++)
19 .{
20. BsonDocument tmpDoc = res. ElementAt (I );
21. // do something you want
22 .}
// Obtain Collection
Relational Database db = server. GetDatabase ("aa ");
Repeated collection colSheng = db. GetCollection ("sheng ");

// Define a query box or query a polygon
Var poly = GeoJson. Polygon (
GeoJson. Position (100, 20 ),
GeoJson. Position (110, 20 ),
GeoJson. Position (110, 40 ),
GeoJson. Position (100, 40 ),
GeoJson. Position (100, 20 ));
// Define a query statement based on the query Polygon
Var queryFilter2 = Query. GeoIntersects ("geo", poly );
// Query and output the cursor
Cur = colSheng. FindAs (QueryFilter2). SetFields ("pyname", "date ");
// Obtain the result
Var res = cur. ToArray ();
For (int I = 0; I <res. Count (); I ++)
{
BsonDocument tmpDoc = res. ElementAt (I );
// Do something you want
}

For spatial indexes, see http://docs.mongodb.org/manual/applications/geospatial-indexes/
This is not detailed here.

Space query operation problems:

When GeoIntersect is used for spatial queries, the query results are inconsistent with ArcGIS. For details, see a BUG in MongoDB (2.6.0 is used currently)

The specific information is as follows (in the command line ):

Coordinates in Collection

[Csharp] view plaincopyprint? 01.> db. test. find ()
02. {"_ id": ObjectId ("535884771dbba31858ad2101"), "geo": {"type": "Polygon", "coordinates": [[96.722, 38.755], [97.3482, 38.6922], [97.1674, 38.0752], [96.5474, 38.1383], [96.722, 38.755]}
> Db. test. find ()
{"_ Id": ObjectId ("535884771dbba31858ad2101"), "geo": {"type": "Polygon", "coordinates": [[96.722, 38.755], [97.3482, 38.6922], [97.1674, 38.0752], [96.5474, 38.1383], [96.722, 38.755]}

Query statement used

[Csharp] view plaincopyprint? 01.> db. test. find ({"geo": {"$ geoIntersects": {"$ geometry": {"type": "Polygon", "coordinates": [[91.0, 33.0], [102.0, 33.0], [102.0, 38.0], [91.0, 38.0], [91.0, 33.0]})
> Db. test. find ({"geo": {"$ geoIntersects": {"$ geometry": {"type": "Polygon", "coordinates": [[91.0, 33.0], [102.0, 33.0], [102.0, 38.0], [91.0, 38.0], [91.0, 33.0]})

Query results:

[Csharp] view plaincopyprint? 01. {"_ id": ObjectId ("535884771dbba31858ad2101"), "geo": {"type": "Polygon", "coordinates": [[96.722, 38.755], [97.3482, 38.6922], [97.1674, 38.0752], [96.5474, 38.1383], [96.722, 38.755]}
{"_ Id": ObjectId ("535884771dbba31858ad2101"), "geo": {"type": "Polygon", "coordinates": [[96.722, 38.755], [97.3482, 38.6922], [97.1674, 38.0752], [96.5474, 38.1383], [96.722, 38.755]}

But we can see that there is only one record in the collection, and the Y coordinate of all points of the record is greater than 38.0. Why does this record intersect with the Box in the statement in the query result... Very strange

Because of this problem, it is not easy to directly use the space query for practical applications. Instead, it uses a flexible method to perform simple space query. After testing, it is found that, this may be due to spatial index problems. This method is faster than the built-in GeoIntersects method.

The general idea is: generate a minimum external rectangle for each record, and obtain the xmax, xmin, ymax, and ymin boundary values, which are saved to the Collection as numerical values, when performing a spatial query, filter the smallest external rectangle first to determine the relationship between the smallest external rectangle and the smallest external rectangle of the polygon in the query statement, the second step is used to determine whether the actual polygon is intersecting through the Ogr component and return the final result.

The code for generating the smallest external rectangle is as follows:

[Csharp] view plaincopyprint? 01. // get Collection
02. Relational Database db = server. GetDatabase ("aa ");
03. Collect collection colsheng = db. GetCollection ("sheng ");
04. // query all records
05. var cur = colsheng. FindAllAs ();
06. long totalCount = cur. Count ();
07. // traverse all records
08. for (int I = 0; I <= totalCount/1000; I ++)
09 .{
10. if (I * 1000> = totalCount) continue;
11. int skip = I * 1000;
12. var cur2 = cur. Clone (). SetSkip (skip). SetLimit (1000 );
13. var lst = cur2.ToArray ();
14. for (int j = 0; j <lst. Count (); j ++)
15 .{
16. // obtain the BsonDocument corresponding to a record
17. BsonDocument doc = lst [j];
18. var id = doc ["_ id"]; // ID of the record
19. BsonDocument geo = doc ["geo"]. ToBsonDocument ();
20. string geostr = geo [1]. ToString (); // Json string of the corresponding spatial information of the record
21. List Coords = GetCoordLstFromString (geostr); // parse the Json string to obtain the coordinates of all vertices (here the subfunction is omitted)
22. double xmin = 181, xmax =-181, ymin = 91, ymax =-91; // Four boundary values. Because the layer is longitude and latitude, the initial values are set to these values.
23. // calculate the maximum and minimum values
24. for (int k = 0; k <coords. Count; k ++)
25 .{
26. if (k % 2 = 0)
27 .{
28. if (coords [k] <xmin) xmin = coords [k];
29. if (coords [k]> xmax) xmax = coords [k];
30 .}
31. else
32 .{
33. if (coords [k] <ymin) ymin = coords [k];
34. if (coords [k]> ymax) ymax = coords [k];
35 .}
36 .}
37. // write the maximum and minimum values to the Collection
38. var tmpQuery = Query. EQ ("_ id", id );
39. var tmpUpdate = MongoDB. Driver. Builders. Update. Set ("xmax", xmax );
40. var tmpres = col02c. Update (tmpQuery, tmpUpdate );
41. tmpUpdate = MongoDB. Driver. Builders. Update. Set ("xmin", xmin );
42. tmpres = col02c. Update (tmpQuery, tmpUpdate );
43. tmpUpdate = MongoDB. Driver. Builders. Update. Set ("ymax", ymax );
44. tmpres = col02c. Update (tmpQuery, tmpUpdate );
45. tmpUpdate = MongoDB. Driver. Builders. Update. Set ("ymin", ymin );
46. tmpres = col02c. Update (tmpQuery, tmpUpdate );
47 .}
48 .}
// Obtain Collection
Relational Database db = server. GetDatabase ("aa ");
Repeated collection colsheng = db. GetCollection ("sheng ");
// Query all records
Var cur = colsheng. FindAllAs ();
Long totalCount = cur. Count ();
// Traverse all records
For (int I = 0; I <= totalCount/1000; I ++)
{
If (I * 1000> = totalCount) continue;
Int skip = I * 1000;
Var cur2 = cur. Clone (). SetSkip (skip). SetLimit (1000 );
Var lst = cur2.ToArray ();
For (int j = 0; j <lst. Count (); j ++)
{
// Obtain the BsonDocument corresponding to a record
BsonDocument doc = lst [j];
Var id = doc ["_ id"]; // ID of the record
BsonDocument geo = doc ["geo"]. ToBsonDocument ();
String geostr = geo [1]. ToString (); // Json string of the corresponding spatial information of the record
List Coords = GetCoordLstFromString (geostr); // parse the Json string to obtain the coordinates of all vertices (here the subfunction is omitted)
Double xmin = 181, xmax =-181, ymin = 91, ymax =-91; // Four boundary values. Because the layer is longitude and latitude, the initial values are set to these values.
// Calculate the maximum and minimum values
For (int k = 0; k <coords. Count; k ++)
{
If (k % 2 = 0)
{
If (coords [k] <xmin) xmin = coords [k];
If (coords [k]> xmax) xmax = coords [k];
}
Else
{
If (coords [k] <ymin) ymin = coords [k];
If (coords [k]> ymax) ymax = coords [k];
}
}
// Write the maximum and minimum values to the Collection.
Var tmpQuery = Query. EQ ("_ id", id );
Var tmpUpdate = MongoDB. Driver. Builders. Update. Set ("xmax", xmax );
Var tmpres = col02c. Update (tmpQuery, tmpUpdate );
TmpUpdate = MongoDB. Driver. Builders. Update. Set ("xmin", xmin );
Tmpres = col02c. Update (tmpQuery, tmpUpdate );
TmpUpdate = MongoDB. Driver. Builders. Update. Set ("ymax", ymax );
Tmpres = col02c. Update (tmpQuery, tmpUpdate );
TmpUpdate = MongoDB. Driver. Builders. Update. Set ("ymin", ymin );
Tmpres = col02c. Update (tmpQuery, tmpUpdate );
}
}

Then there is the query code:

[Csharp] view plaincopyprint? 01. // get Collection
02. Relational Database db = server. GetDatabase ("aa ");
03. Repeated collection colSheng = db. GetCollection ("zy02c ");
04. // Step 1: Filter by four boundaries,
05. var query = Query. and (Query. GT ("xmax", 91.0), Query. LT ("xmin", 102.0), Query. GT ("ymax", 33.0), Query. LT ("ymin", 38.0 ));
06. var cur = colSheng. FindAs (Query );
07. // define the condition polygon for second Space Operation (definition in Ogr format)
08. Geometry queryGeoLR = new Geometry (wkbGeometryType. wkbLinearRing );
09. queryGeoLR. AddPoint (91.0, 33.0, 0 );
10. queryGeoLR. AddPoint (102.0, 33.0, 0 );
11. queryGeoLR. AddPoint (102.0, 38.0, 0 );
12. queryGeoLR. AddPoint (91.0, 38.0, 0 );
13. queryGeoLR. AddPoint (91.0, 33.0, 0 );
14. Geometry queryGeo = new Geometry (wkbGeometryType. wkbPolygon );
15. queryGeo. AddGeometry (queryGeoLR );
16. // the result of the loop Query
17. var lst = cur. ToArray ();
18. for (int I = lst. Length-1; I> = 0; I --)
19 .{
20. // obtain the BsonDocument corresponding to the current record
21. BsonDocument doc = lst [I];
22. var id = doc ["_ id"]; // ID of the current record
23. BsonDocument geo = doc ["geo"]. ToBsonDocument ();
24. string geostr = geo [1]. ToString (); // Json string of the space information of the current record
25.
26. // obtain the coordinate value through the Json string and generate the corresponding Geometry object
27. List Coords = GetCoordLstFromString (geostr );
28. Geometry resGeoLR = new Geometry (wkbGeometryType. wkbLinearRing );
29. for (int j = 0; j <coords. Count/2; j ++)
30 .{
31. resGeoLR. AddPoint_2D (coords [j], coords [j + 1]);
32 .}
33. resGeoLR. AddPoint_2D (coords [0], coords [1]);
34. Geometry resGeo = new Geometry (wkbGeometryType. wkbPolygon );
35. resGeo. AddGeometry (resGeoLR );
36. // determine whether the Geometry and the condition polygon intersect.
37. if (resGeo. Intersects (queryGeo ))
38 .{
39. // do something
40 .}
41 .}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.