Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
05/18/2022 05:32:26 AM (4 years ago)
Author:
imath
Message:

Improve group members count query performance

[13103] introduced a change in 10.0.0 that can be very time consuming when a group has a lot of members.

To keep the main improvements of the referenced commit (only refreshing group members count when a user joins or leaves a group) but optimize queries performance, we are introducing a new way to count group members in the BP_Group_Member_Query.

We are also introducing a way to defer group members count when adding a batch of members to a group. Using bp_groups_defer_group_members_count() avoids to refresh the count each time a member of this batch is added. For more information about how to use this function, you can have a look at how BuddyPress is using it into src/bp-groups/bp-groups-admin.php.

Props dd32, espellcaste

See #8688 (trunk)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-groups/classes/class-bp-group-member-query.php

    r13108 r13280  
    5151
    5252        /**
     53         * Constructor.
     54         *
     55         * @since 10.3.0
     56         *
     57         * @param string|array|null $query See {@link BP_User_Query}.
     58         */
     59        public function __construct( $query = null ) {
     60                $qv = bp_parse_args(
     61                        $query,
     62                        array(
     63                                'count' => false, // True to perform a count query. False otherwise.
     64                        )
     65                );
     66
     67                parent::__construct( $qv );
     68        }
     69
     70        /**
    5371         * Set up action hooks.
    5472         *
     
    6381                }
    6482
    65                 // Set the sort order.
    66                 add_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) );
    67 
    68                 // Set up our populate_extras method.
    69                 add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     83                if ( ! $this->query_vars_raw['count'] ) {
     84                        // Set the sort order.
     85                        add_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) );
     86
     87                        // Set up our populate_extras method.
     88                        add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     89                } else {
     90                        $this->query_vars_raw['orderby'] = 'ID';
     91                }
     92        }
     93
     94        /**
     95         * Use WP_User_Query() to pull data for the user IDs retrieved in the main query.
     96         *
     97         * If a `count` query is performed, the function is used to validate existing users.
     98         *
     99         * @since 10.3.0
     100         */
     101        public function do_wp_user_query() {
     102                if ( ! $this->query_vars_raw['count'] ) {
     103                        return parent::do_wp_user_query();
     104                }
     105
     106                /**
     107                 * Filters the WP User Query arguments before passing into the class.
     108                 *
     109                 * @since 10.3.0
     110                 *
     111                 * @param array         $value Array of arguments for the user query.
     112                 * @param BP_User_Query $this  Current BP_User_Query instance.
     113                 */
     114                $wp_user_query = new WP_User_Query(
     115                        apply_filters(
     116                                'bp_group_members_count_query_args',
     117                                array(
     118                                        // Relevant.
     119                                        'fields'      => 'ID',
     120                                        'include'     => $this->user_ids,
     121
     122                                        // Overrides
     123                                        'blog_id'     => 0,    // BP does not require blog roles.
     124                                        'count_total' => false // We already have a count.
     125
     126                                ),
     127                                $this
     128                        )
     129                );
     130
     131                // Validate existing user IDs.
     132                $this->user_ids = array_map( 'intval', $wp_user_query->results );
     133                $this->results  = $this->user_ids;
     134
     135                // Set the total existing users.
     136                $this->total_users = count( $this->user_ids );
    70137        }
    71138
     
    474541                return wp_list_pluck( $group_user_ids, 'user_id' );
    475542        }
     543
     544        /**
     545         * Perform a database query to populate any extra metadata we might need.
     546         *
     547         * If a `count` query is performed, the function is used to validate active users.
     548         *
     549         * @since 10.3.0
     550         */
     551        public function populate_extras() {
     552                if ( ! $this->query_vars_raw['count'] ) {
     553                        return parent::populate_extras();
     554                }
     555
     556                // Validate active users.
     557                $active_users    = array_filter( BP_Core_User::get_last_activity( $this->user_ids ) );
     558                $active_user_ids = array_keys( $active_users );
     559                $this->results   = array_intersect( $this->user_ids, $active_user_ids );
     560
     561                // Set the total active users.
     562                $this->total_users = count( $this->results );
     563        }
    476564}
Note: See TracChangeset for help on using the changeset viewer.