| 1 | = !MapGuide RFC 175 - WFS GetFeature support for hit count = |
| 2 | |
| 3 | This page contains a change request (RFC) for the !MapGuide Open Source project. |
| 4 | More !MapGuide RFCs can be found on the [wiki:MapGuideRfcs RFCs] page. |
| 5 | |
| 6 | == Status == |
| 7 | |
| 8 | ||RFC Template Version||(1.0)|| |
| 9 | ||Submission Date||13 Jul 2019|| |
| 10 | ||Last Modified||13 Jul 2019|| |
| 11 | ||Author||Jackie Ng|| |
| 12 | ||RFC Status||draft|| |
| 13 | ||Implementation Status||pending|| |
| 14 | ||Proposed Milestone||4.0|| |
| 15 | ||Assigned PSC guide(s)||(when determined)|| |
| 16 | ||'''Voting History'''||(vote date)|| |
| 17 | ||+1|||| |
| 18 | ||+0|||| |
| 19 | ||-0|||| |
| 20 | ||-1|||| |
| 21 | ||no vote|| || |
| 22 | |
| 23 | == Overview == |
| 24 | |
| 25 | This RFC proposes to add support for `resultType=hits` in WFS 1.1.0 `GetFeature` requests |
| 26 | |
| 27 | == Motivation == |
| 28 | |
| 29 | With WFS 1.1.0 onwards, a WFS client may pass an optional `resultType=hits` parameter to request a raw |
| 30 | total of matching features instead of the full set of feature data in the requested format. |
| 31 | |
| 32 | This parameter is an optional part of the WFS 1.1.0 spec that MapGuide currently does not support. As a |
| 33 | result, a WFS client currently has no way to request a feature total from a MapGuide WFS service without |
| 34 | requesting the full feature data, which is an extremely inefficient way to count features. |
| 35 | |
| 36 | == Proposed Solution == |
| 37 | |
| 38 | Add support for `resultType=hits` for WFS 1.1.0 `GetFeature` requests. |
| 39 | |
| 40 | To support this we'll add a new internal `GetWfsFeatureTotal` method which does the same feature query as |
| 41 | the original `GetFeature` request, but raw spins the resulting feature reader on the server-side to obtain |
| 42 | the feature total. |
| 43 | |
| 44 | {{{ |
| 45 | class MG_PLATFORMBASE_API MgFeatureService : public MgService |
| 46 | { |
| 47 | ... |
| 48 | INTERNAL_API: |
| 49 | //////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 50 | /// \brief |
| 51 | /// Retrieves the total feature count for the given WFS query |
| 52 | /// |
| 53 | /// \note1 |
| 54 | /// |
| 55 | /// <!-- Syntax in .Net, Java, and PHP --> |
| 56 | /// \htmlinclude DotNetSyntaxTop.html |
| 57 | /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures); |
| 58 | /// \htmlinclude SyntaxBottom.html |
| 59 | /// \htmlinclude JavaSyntaxTop.html |
| 60 | /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures); |
| 61 | /// \htmlinclude SyntaxBottom.html |
| 62 | /// \htmlinclude PHPSyntaxTop.html |
| 63 | /// virtual int GetWfsFeatureTotal(MgResourceIdentifier featureSourceId, string featureClass, string filter, int maxFeatures); |
| 64 | /// \htmlinclude SyntaxBottom.html |
| 65 | /// |
| 66 | /// \param featureSourceId (MgResourceIdentifier) |
| 67 | /// The resource identifier defining the |
| 68 | /// location of the feature source in |
| 69 | /// the repository. |
| 70 | /// \param featureClass (String/string) |
| 71 | /// The feature class containing the features to retrieve. |
| 72 | /// \param filter (String/string) |
| 73 | /// An XML string containing the definition for an OGC filter |
| 74 | /// \param maxFeatures (int) |
| 75 | /// If greater than 0 and less than the real computed total, this will be the value returned |
| 76 | /// |
| 77 | /// \remarks |
| 78 | /// This method is primarily used to service the WFS GetFeatures operation in resultType=hits mode |
| 79 | /// where a total is desired over requesting the whole set of feature data |
| 80 | /// |
| 81 | /// \return |
| 82 | /// Returns an MgByteReader containing the requested feature information. |
| 83 | /// |
| 84 | /// \exception MgInvalidArgumentException |
| 85 | /// |
| 86 | /// \since 4.0 |
| 87 | virtual INT32 GetWfsFeatureTotal(MgResourceIdentifier* featureSourceId, |
| 88 | CREFSTRING featureClass, |
| 89 | CREFSTRING filter, |
| 90 | INT32 maxFeatures) = 0; |
| 91 | }; |
| 92 | }}} |
| 93 | |
| 94 | A question one may ask is why raw spin a feature reader to obtain the feature total instead of something |
| 95 | more efficient like a SelectAggregates with `COUNT()`? The problem lies in the `maxFeatures` parameter that |
| 96 | can be specified in any WFS `GetFeatures` request. If this parameter is present when requesting a hit count, |
| 97 | *it needs to be respected* and none of the optimal counting methods we have allow us to specify an upper limit. As |
| 98 | a result, raw spinning a feature reader is the only practical solution. |
| 99 | |
| 100 | A sample `GetFeature` response with `resultType=hits` would look like this: |
| 101 | |
| 102 | {{{ |
| 103 | <?xml version="1.0" encoding="utf-8" ?> |
| 104 | <wfs:FeatureCollection xmlns:gml="http://www.opengis.net/gml" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ns55197509="http://fdo.osgeo.org/schemas/feature/ns55197509" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/base/feature.xsd http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" numberOfFeatures="11" /> |
| 105 | }}} |
| 106 | |
| 107 | If JSON format is requested, the response would look like this: |
| 108 | |
| 109 | {{{ |
| 110 | { |
| 111 | "numberOfFeatures": 11 |
| 112 | } |
| 113 | }}} |
| 114 | |
| 115 | This implementation exists in the [https://trac.osgeo.org/mapguide/browser/sandbox/jng/wfs_hits wfs_hits sandbox]. Upon adoption of this RFC, will be merged into trunk. |
| 116 | |
| 117 | == Implications == |
| 118 | |
| 119 | This parmameter is only available for WFS 1.1.0. For WFS 1.0.0, this parameter has no effect. |
| 120 | |
| 121 | Another important note is that the feature total will only be included *if and only if* `resultType=hits` is |
| 122 | included. It is not included in regular `GetFeature` responses as it would require 2 queries (1 to count, 1 for the |
| 123 | original query) and for the sake of simplicity in implementation that it was carried out in this way. |
| 124 | |
| 125 | == Test Plan == |
| 126 | |
| 127 | Verify `resultType=hits` returns hit count only for WFS 1.1.0 requests |
| 128 | |
| 129 | == Funding / Resources == |
| 130 | |
| 131 | Community |