geosolutions-it / MapStore2

The solution to create and share maps, dashboards, geostories with 3D support on the web. And it is open-source too!
https://mapstore.geosolutionsgroup.com/
Other
504 stars 391 forks source link

Support combination of advanced filters and Quick filter for feature grid #6226

Open offtherailz opened 3 years ago

offtherailz commented 3 years ago

Description

An current limitation of the filtering system is that the spatialField is an array of spatial filter that can have only one operator. With the introduction of multiple spatial quick filters (from feature grid) we now need to manage the combination of AdvancedFilterSpatialFilter AND (quickSpatialFilter1 OR quickSpatialFilter2).

For the moment the quick filter wins over the advanced spatial filter, if present.

How to reproduce

Expected Result The resulting filter is the cobination of `Advanced * (QF1 + QF2)

Current Result The advanced is skipped (Because AND + OR is not supported yet)

Browser info (use this site: https://www.whatsmybrowser.org/ for non expert users) | Browser Affected | Version | |---|---| |Internet Explorer| | |Edge| | |Chrome| | |Firefox| | |Safari| |

Other useful information

offtherailz commented 3 years ago

This issue is caused by the structure of filters that is modelled on the panel data structure (and it shouldn't be). Because we need also to implement some of functionalities from #6625 I propose a refactor of current filter system to allow an easier of future or custom tools

RFC

@mbarto , @allyoucanmap , @tdipisa , @MV88

Here some notes about the current filtering functionalities, to understand the complexity of the current system and the things to change in order to have a system that can adapt to future requirements.

Filter structure

The internal fliter object structure is made on the model of the query panel and not well separated from the WFS:

{
    featureTypeName: 'gs:us_states', // ← Used for select a different layer, see #6430
    filterType: 'OGC',
    ogcVersion: '1.1.0',
    pagination: {
      startIndex: 0,
      maxFeatures: 100000 // ← this is used to deactivate virtual scrolling when multiple selection is active
    },
    spatialField: [ // this is the original spatial field of the query panel (1 element) extended to array because now in feature grid we need multiple geometric filters
      {
        attribute: 'the_geom', 
geometry: {center: [ // includes circle geometry info, to repopulate the query panel in a second time
            -12997963.78583765,
            4693845.032936105
          ],
          coordinates:  [...]
          extent: [
            -13017531.665078655,
            4674277.1536951,
            -12978395.906596646,
            4713412.912177109
          ],
          projection: 'EPSG:900913',
          radius: 19567.879241004586,
          type: 'Polygon'
        },
        method: 'Circle',
        operation: 'INTERSECTS'
      }, {...}    ],
    groupFields: [  // ← Groups, now used also for quick filters
      {
        id: 1615198153790,
        index: 0,
        logic: 'AND'
      },
      {
        groupId: 1615198153790,
        logic: 'AND',
        id: '1_1',
        index: 1
      }
    ],
    filterFields: [ // ← The attribute fields, linked to groups by groupId
      {
        attribute: 'STATE_FIPS',
        rowId: 1615198153790,
        type: 'string',
        groupId: '1_1',
        operator: 'ilike',
        value: '32'
      }
    ],
    spatialFieldOperator: '' //← Operator to apply multiple spatial filter
  }
}

Moreover inside the code there is support for “simpleFilter”: coming for a previous version of the query panel, or custom development, maybe it is not used anymore. The filters from this field are all in and with the others.

Now as you can see this structure has many limitations:

This structure has some utilities in FilterUtils that are confusing

They produce only filter (CQL/OGC) based on the structure above, without any kind of support

In order to provide support for development, we created some utilities in utils/ogc

layerFilter property inside a layer has the filter object structure to:

These filters are saved in maps, so we need to maintain retro-compatibility.

Quick filters:

they have this shape

[{
attribute: "STATE_ABBR"
operator: "ilike"
rawValue: ""
type: "string"
}, {
attribute: "SUB_REGION"
operator: "ilike"
rawValue: "W N Cen"
type: "string"
value: "W N Cen"
}]

Also these filters are saved in dashboards. Anyway this is an internal structure, flat by nature, and can be converted in an and filter (that is implicit for the purpose of this tool). This different structure doesn't look to be problematic at all.

Conclusions

The whole MapStore filtering functionalities are confusing and makes difficult to develop.

Adding ID filtering to the current system add even more complexity to a system that need to be simplified and uniformed.

Proposal

A possible solutions to keep retro-compatibility is to add a "version" entry to determine if the filter has old or new style.

The new style proposed, lets say version: 2 is the nested structure present in CQL filter management, that is more rational and processable, because of it's tree structure.

In order to match the current query panel with the structure of version 2. We will have an AND filter as root, that includes the actual spatialFilter, layerFilter and attributeFilter.
If possible then whe should move all the logic that handles these 3 fields only inside a conversion tool, to keep retro-compatibility, and inside the query panel. Outside we should use only the new structure.

Some utility functions (like FilterBuilder and other utils) will allow to compose filters without needing to know and manipulate the internal structure.