.. _mongo_tutorial: MongoDB Tutorial ================ This tutorial demonstrates how to use app-schema plugin with a MongoDB data store. This tutorial will focus on the MongoDB data store specificities is highly recommended to read the app-schema documentation before. Use Case -------- The use case for this tutorial will be to serve through app-schema the information about some meteorological stations stored in a MongoDB database. Note that this use case is completely fictional and only used to demonstrate the MongoDB and app-schema integration. First of all let's insert some test data in a MongoDB data store: .. code-block:: json db.stations.insert({ "id": "1", "name": "station 1", "contact": { "mail": "station1@mail.com" }, "geometry": { "coordinates": [ 50, 60 ], "type": "Point" }, "measurements": [ { "name": "temp", "unit": "c", "values": [ { "time": 1482146800, "value": 20 } ] }, { "name": "wind", "unit": "km/h", "values": [ { "time": 1482146833, "value": 155 } ] } ] }) db.stations.insert({ "id": "2", "name": "station 2", "contact": { "mail": "station2@mail.com" }, "geometry": { "coordinates": [ 100, -50 ], "type": "Point" }, "measurements": [ { "name": "temp", "unit": "c", "values": [ { "time": 1482146911, "value": 35 }, { "time": 1482146935, "value": 25 } ] }, { "name": "wind", "unit": "km/h", "values": [ { "time": 1482146964, "value": 80 } ] }, { "name": "pression", "unit": "pa", "values": [ { "time": 1482147026, "value": 1019 }, { "time": 1482147051, "value": 1015 } ] } ] }) db.stations.createIndex({ "geometry": "2dsphere" }) This is the schema that will be used to do the mappings in app-schema: .. code-block:: xml Mappings -------- MongoDB objects may contain nested elements and nested collections. The following three functions make possible to select nested elements and link nested collections using a JSON path: .. list-table:: :widths: 20 30 50 * - **Function** - **Example** - **Description** * - jsonSelect - jsonSelect('contact.mail') - Used to retrieve the value for the mapping from a MongoDB object. * - collectionLink - collectionLink('measurements.values') - Used when chaining entities with a nested collection. * - collectionId - collectionId() - Instructs the mapper to generate a ID for the nested collection. * - nestedCollectionLink - nestedCollectionLink() - Used on the nested collection to create a link with the parent feature. A station data is composed of some meta-information about the station and a list of measurements. Each measurement as some meta-information and contains a list of values. The mappings will contain three top entities: the station, the measurements and the values. Follows a the complete mappings file: .. code-block:: xml st http://www.stations.org/1.0 gml http://www.opengis.net/gml data_source data_store mongodb://{mongoHost}:{mongoPort}/{dataBaseName} namespace http://www.stations.org/1.0 schema_store file:{schemaStore} data_store_type complex stations.xsd data_source {collectionName} st:StationFeature st:StationFeature jsonSelect('id') st:name jsonSelect('name') st:contact/st:mail jsonSelect('contact.mail') st:measurement collectionLink('measurements') aaa FEATURE_LINK[1] true st:geometry jsonSelect('geometry') data_source {collectionName} aaa st:Measurement st:Measurement collectionId() st:name jsonSelect('name') st:unit jsonSelect('unit') st:values collectionLink('values') st:Value FEATURE_LINK[2] true FEATURE_LINK[1] nestedCollectionLink() data_source {collectionName} st:Value st:Value collectionId() st:timestamp jsonSelect('time') st:value jsonSelect('value') FEATURE_LINK[2] nestedCollectionLink() The mappings for the attributes are straightforward, for example the following mapping: .. code-block:: xml st:contact/st:mail jsonSelect('contact.mail') The mapping above defines that the contact mail for a station will be available at the JSON path ``contact.mail`` and that the correspondent XML schema element is the XPATH ``st:contact/st:mail``. The feature chaining is a little bit more complex. Let's take as an example the chaining between ``StationFeature`` and ``Measurement`` features. In the ``StationFeature`` feature type the link to the Measurement entity is defined with the following mapping: .. code-block:: xml st:measurement collectionLink('measurements') st:Measurement FEATURE_LINK[1] true and in the ``Measurement`` feature type the link to the parent feature is defined with the following mapping: .. code-block:: xml FEATURE_LINK[1] nestedCollectionLink() With the two mapping above we tie the two features types together. When working with a MongoDB data store this mappings will always be petty much the same, only the nested collection path and the feature link index need to be updated. Note that the JSON path of the nested collections attributes are relative to the parent. Querying -------- To create an MongoDB app-schema layer in GeoServer, the app-schema extension and the mongo-complex extension needs to be installed. A workspace for each name space declared in the mappings file needs to be created, in this case the workspace ``st`` with URI ``http://www.stations.org/1.0`` needs to be created. No need to create a ``gml`` workspace. Creating a MongoDB app-schema layer is similar to any other app-schema layer, just create an app-schema store pointing to the correct mappings file and select the layer correspondent to the top entity, in this case ``st:StationFeature``. Is possible to query with WFS complex features encoded in GML and GeoJson using complex features filtering capabilities. For example, querying all the stations that have a measurement value with a time stamp superior to ``1482146964``: .. code-block:: xml st:StationFeature/st:measurement/st:values/st:timestamp 1482146964