Eficiencia en la visualización de autores aleatorios basados en grandes bases de datos

2

Estoy intentando mostrar una lista de 5 autores al azar . Aquí hay algunas soluciones que he encontrado:

enlace enlace

Actualmente estoy usando la solución anterior, excepto que uso WP_User_Query así:

$args  = array(
    'role' => 'subscriber'
);
$wp_user_query = new WP_User_Query($args);
$authors = $wp_user_query->get_results();

// Shuffle list to get random results
shuffle($authors);

Sin embargo, a mi entender por amateur , buscará toda la lista de usuarios . Entonces me pregunto si tuve alrededor de 2000-5000 usuarios (o más) , ¿esto afectará a carga de página drásticamente? ¿Cómo puedo hacer esto más eficiente?

ACTUALIZAR :

¿También sería array_rand() un método más eficiente en comparación con shuffle() ?

    
pregunta Giraldi 21.10.2013 - 05:58

2 respuestas

3

Si le preocupa la eficiencia, puede utilizar la API de transitorios para almacenar la consulta. El almacenamiento de algo que desea aleatorizar puede parecer contrario a la intuición, pero si almacena toda la consulta, siempre puede aleatorizar y manipular la matriz resultante para obtener los resultados que desea.

A continuación, le indicamos cómo obtener todos los suscriptores y almacenarlos de forma transitoria, con un código de PHP directo al final para mezclar / aleatorizar el resultado y luego eliminar los primeros 5 resultados usando array_slice()

if ( false === ( $users = get_transient( 'get_all_subscribers' ) ) ) {
     // this code runs when there is no valid transient set

    $args  = array(
        'role'   => 'subscriber'
    );

    $wp_user_query = new WP_User_Query( $args );

    $users = $wp_user_query->get_results();

    set_transient( 'get_all_subscribers', $users );
}

// proceed with data normally
// randomize the stored result
shuffle( $users );
$rand_users = array_slice( $users, 0, 5 );

var_dump( $rand_users );

y luego, para asegurarnos de que el transitorio esté actualizado, lo eliminaremos cuando se actualice o agregue un usuario:

// Create a simple function to delete our transient
function delete_all_subscribers_transient() {
     delete_transient( 'get_all_subscribers' );
}
// Add the function to the profile_update and user_registration hooks
add_action( 'profile_update', 'delete_all_subscribers_transient' );
add_action( 'user_register', 'delete_all_subscribers_transient' );
    
respondido por el helgatheviking 21.10.2013 - 11:13
3

No desea obtener todos los usuarios si solo necesita 5 .

Si desea usar WP_User_Query() para obtener 5 usuarios al azar, puede intentar usar el gancho pre_user_query para sobrescribir la parte orderby :

$args  = array(
    'role'   => 'subscriber',
    'number' => 5,
);
add_action( 'pre_user_query', 'my_pre_user_query' );
$wp_user_query = new WP_User_Query( $args );

donde

function my_pre_user_query( $q ){
    $q->query_orderby = ' ORDER BY RAND() ';

    // remove the hook
    remove_action( current_filter(), __FUNCTION__ );
}

Actualización:

Este artículo contiene un Truco para reducir el número de filas, utilizando un especial Condición WHERE , antes de que ORDER BY RAND() se active ... por lo que yo entiendo.

La condición WHERE en su caso podría ser

WHERE RAND()<(SELECT ((5/COUNT(*))*10) FROM wp_users)

Entonces, si tiene un gran número de usuarios, podría probar esta devolución de llamada de acción modificada:

function my_pre_user_query( $q ){
    $q->query_where = str_replace( 'WHERE 1=1', 'WHERE RAND()<(SELECT ((5/COUNT(*))*10) FROM wp_users) ', $q->query_where );
    $q->query_orderby = ' ORDER BY RAND() ';

    // remove hook
    remove_action( current_filter() , __FUNCTION__ );
}

¡Si el truco del artículo anterior está funcionando!

Aquí hay una versión más general de la devolución de llamada modificada:

function my_pre_user_query( $q ){

    $limit = preg_replace( '/[^\d]/', '', $q->query_limit );

    $from   = 'WHERE 1=1';
    $to     = sprintf( 'WHERE RAND()<(SELECT ((%d/COUNT(*))*10) FROM %susers)', 
                        $limit, 
                        $GLOBALS['wpdb']->prefix 
             );

    $q->query_where   = str_replace( $from, $to, $q->query_where );
    $q->query_orderby = ' ORDER BY RAND() ';

    // remove the hook    
    remove_action( current_filter() , __FUNCTION__ );
}
    
respondido por el birgire 21.10.2013 - 10:36

Lea otras preguntas en las etiquetas