Problem/Motivation
Views supports a minimal set of aggregate functions that are hard coded into the default query plugin. It would be useful to have a way to add support for the full range of SQL aggregates available in MySQL & PostgreSQL (GROUP_CONCT/STRING_AGG, VARIANCE, ...), as well as providing a means of supporting the extended set of OGC spatial aggregates supported by PostgreSQL (ST_Union, ST_ClusterWithin, ...), and allowing any other user-defined aggregates that may be available.
Proposed resolution
- Provide a plugin for defining new aggregates.
- Use CTools-based methods to expose plugin.
- This is a backport of a proposed solution for D8 (Support Plugins for Views Aggregate (2662548))
Code 1: Patch excerpt, 1 line to add aggregate definitions via plugin.
--- a/plugins/views_plugin_query_default.inc
+++ b/plugins/views_plugin_query_default.inc
@@ -1592,7 +1592,7 @@ class views_plugin_query_default extends views_plugin_query {
'sort' => 'views_handler_sort_group_by_numeric',
),
)
- );
+ ) + views_fetch_plugin_data('query_aggregate');
}
/**
For further details, see "Implementation Example", and for further details a related issue with patch for implementation in D7 "Support Plugins for Views Aggregate in D7").
Remaining tasks
Add ctools plugin search in aggregate definition function- Create Plugins for all default aggregate functions in order to provide implementation example.
- Remove hard-coded default aggregates from views_plugin_query_default.inc
- Test
User interface changes
None.
API changes
Add Annotation-based plugin support for ViewsAggregate
Data model changes
None.
Implementation Example
Code 2: Sample implementation of VAR_SAMP in Drupal 7 using Ctools plugin.
function views_views_plugins() {
return array(
'query_aggregate' => array(
'var_samp' => array(
'title' => t('Sample Variance'),
'method' => 'views_query_default_aggregation_method_simple',
'handler' => array(
'argument' => 'views_handler_argument_group_by_numeric',
'filter' => 'views_handler_filter_group_by_numeric',
'sort' => 'views_handler_sort_group_by_numeric',
),
),
...
Original report by joachim
function get_aggregation_info() {
// @todo -- need a way to get database specific and customized aggregation
// functions into here.
What's the best way to do this?
Should aggregation functions be another type of plugin?
(Background for this is that for Commerce product node displays it would be useful to have a GROUP_CONCAT available.)
Comments
Comment #1
dawehnerWell i'm wondering why an alter hook in that function wouldn't help?
Another kind of plugin type would definitive quite complicated
Comment #2
joachim CreditAttribution: joachim commentedSure, we could drupal_alter that list.
But the aggregation items defined in that function refer to methods of the views_plugin_query_default class. Presumably, a module altering an item into the list would need to be able define a function to call instead of a method.
Comment #3
joachim CreditAttribution: joachim commentedAlso, the GROUP_CONCAT option could feasibly use further UI options.
What do you think about adding GROUP_CONCAT to Views? It could be useful for things like taxonomy terms, if field handlers can be made aware of the need to explode() their incoming values before formatting them.
Comment #4
joachim CreditAttribution: joachim commentedI've had a go at the GROUP_CONCAT over here: #1362524: add GROUP_CONCAT aggregate function; and move aggregate function helpers to a query extender?.
Comment #5
robertwb CreditAttribution: robertwb commentedI think that the simplest appraoch here is to use the existing hook_views_plugin system, and define a new "type" of plugin called "query_aggregate". The new "type" is automatically created whenever a module returns something via hook_views_plugins whose key is not already in the plugins array. This approach results in only a single line of Views code being modified, does not require any new hooks, and allows any module to provide aggregates very simply (provided that they can use the existing views aggregate methods). The code block below is an example for adding a geospatial UNION (st_union) aggregate for a geofield, likely I will submit this as a patch to geofield. The attached patch is all that is required to support the aggregate definition.
Comment #6
robertwb CreditAttribution: robertwb commentedComment #7
robertwb CreditAttribution: robertwb commentedComment #8
joachim CreditAttribution: joachim commentedThis probably should be added to D8 core first, then backported.
Comment #9
robertwb CreditAttribution: robertwb commentedThanks for taking a look @joachim, I created a D8 implementation which mirrors this quite closely, though the plugin stuff is obviously a bit different- still I think it it reasonable to consider it a back port. Updating this to have the D8 issue as a parent.
Comment #10
robertwb CreditAttribution: robertwb commentedComment #11
robertwb CreditAttribution: robertwb commentedComment #12
robertwb CreditAttribution: robertwb commentedComment #13
robertwb CreditAttribution: robertwb commentedComment #14
robertwb CreditAttribution: robertwb commentedAttaching an example module implementing the var_pop and var_samp aggregate functions.
Comment #15
robertwb CreditAttribution: robertwb commentedComment #17
dawehnerThere we go
Comment #18
dawehnerComment #20
robertwb CreditAttribution: robertwb commentedThe issue with D8 still seems to be lingering, but this has been committed in D7 - https://www.drupal.org/node/1359298 and if your interest is spatial aggregates I have posted up an example.