Comment étendre WP_Query pour inclure une table personnalisée dans la requête?
-
-
Ajoutez un lien vers les réponses Mikes,s'il vousplaît.Add a link to Mikes answers, please.
- 0
- 2012-04-26
- kaiser
-
pouvez-vous donner unexemple de ce que vous demanderiez?`WP_Query` sert à obtenir desmessages,et jene comprendspas comment celaest lié auxmessages.can you give an example of what you would be querying for? `WP_Query` is for getting posts, and I'm failing to understand how this ties to posts.
- 1
- 2012-04-26
- mor7ifer
-
@kaiser J'aimis àjour la question avec des liens vers les réponses de Mike.@kaiser I have updated the question with links to Mike's answers.
- 0
- 2012-04-26
- John
-
@m0r7if3r »Je veux étendre WP_Querypour queje puisse limiter lesmessages récupérés à celui de,uniquementpar le (s) chef (s) d'un utilisateur«,donc similaire à «obtenir lesmessagespar auteur».@m0r7if3r »I want to extend WP_Query so that I can limit posts fetched to that of, only by the leader(s) of a user«, so similar to "get posts by author".
- 0
- 2012-04-26
- kaiser
-
@John Leproblèmeest le suivant: comment déterminez-vous quiest le véritable leader?Je suppose que vouspouvez suivreplusieurspersonnes ...@John The problem is: How would you determine who the actual leader is? I guess you can follow several people...
- 0
- 2012-04-26
- kaiser
-
@m0r7if3r Postsestexactement ce queje dois rechercher.Mais lespublications à récupérer doivent être rédigéespar des utilisateurs répertoriés comme leaders d'un certain utilisateur dans letableaupersonnalisé.Donc,en d'autrestermes,je veux dire à WP_Query,allez cherchertous lesmessages detous les utilisateurs qui sont répertoriés comme chefs d'un utilisateur ayant un ID «10» dans letableaupersonnalisé.@m0r7if3r Posts is exactly what I need to query for. But the posts to be fetched should be by users who are listed as leaders of a certain user in the custom table. So, in other words I want to tell WP_Query, go fetch all posts by all users who are listed as leaders of a user having an ID '10' in the custom table.
- 2
- 2012-04-26
- John
-
@kaiser Certes,un utilisateurpeuten suivreplusieurset,par conséquent,lenombre de dirigeants d'un utilisateurpeut être élevé.L'idéeest donc de récupérertoutes lespublications detous les dirigeants d'un utilisateur.Jene saispas siget_posts_by_author SQLfonctionne avecplusieurs auteurs.@kaiser Certainly, a user could follow many and hence the number of leaders to a user could be many. So, the idea is to fetch all posts of all leaders of a user. I am not sure if get_posts_by_author SQL works with multiple authors.
- 0
- 2012-04-26
- John
-
4 réponses
- votes
-
- 2012-05-22
Je réponds à cette questiontrèstardivementet jem'enexcuse. J'avais étébeaucouptrop occupépar les délaispourm'occuper de cela.
Ungrandmerci à @m0r7if3ret @kaiserpourm'avoirfourni les solutions debase quej'aipu étendreet implémenter dansmon application. Cette réponsefournit des détails surmon adaptation des solutionsproposéespar @m0r7if3ret @kaiser.
Tout d'abord,permettez-moi d'expliquerpourquoi cette question a étéposéeen premier lieu. Àpartir de la questionet de ses commentaires,onpourrait déduire quej'essaie d'amener WP_Query àextraire lesmessages detous les utilisateurs (dirigeants) qu'un utilisateur donné (suiveur) suit. La relationentre l'adepteet le leaderest stockée dans unetablepersonnalisée
follow
. La solution laplus courante à ceproblème consiste àextraire les ID utilisateur detous les leaders d'un suiveur dutableau suivantet à leplacer dans untableau. Voir ci-dessous:global $wpdb; $results = $wpdb->get_results($wpdb->prepare('SELECT leader_id FROM cs_follow WHERE follower_id = %s', $user_id)); foreach($results as $result) $leaders[] = $result->leader_id;
Unefois que vous avez letableau de leaders,vouspouvez lepasser comme argument à WP_Query. Voir ci-dessous:
if (isset($leaders)) $authors = implode(',', $leaders); // Necessary as authors argument of WP_Query only accepts string containing post author ID's seperated by commas $args = array( 'post_type' => 'post', 'posts_per_page' => 10, 'author' => $authors ); $wp_query = new WP_Query( $args ); // Normal WordPress loop continues
La solution ci-dessusest lemoyen leplus simple d'obtenir les résultats souhaités. Cependant,iln'estpas évolutif. Aumoment où vous avez un adepte qui suit des dizaineset desmilliers de leaders,letableau résultant d'ID de leader deviendraitextrêmementimportantet forcerait votre site WordPress à utiliser 100 Mo - 250 Mo demémoire à chaque chargement depageet finiraitparplanter le site. La solution auproblème consiste àexécuter une requête SQL directement sur labase de donnéeset à récupérer lespublicationspertinentes. C'est alors que la solution de @m0r7if3rest venue au secours. Suite à la recommandation de @ kaiser,j'aientrepris detester les deuximplémentations. J'aiimportéenviron 47K utilisateurs àpartir d'unfichier CSVpour lesenregistrer sur unenouvelleinstallation detest de WordPress. L'installationexécutait lethème Twenty Eleven. Suite à cela,j'ai lancé uneboucleforpour que 50 utilisateurs suiventtous les autres utilisateurs. La différence detemps de requêtepour les solutions @kaiseret @m0r7if3r était stupéfiante. La solution de @ kaiserprenaitnormalementenviron 2 à 5 secondespour chaque requête. La variation queje présume seproduit lorsque WordPressmet en cache les requêtespour une utilisation ultérieure. D'autrepart,la solution de @m0r7if3r a démontré untemps de requête de 0,02msen moyenne. Pourtester les deux solutions,j'avais l'indexation ONpour la colonne leader_id. Sansindexation,letemps de requête a considérablement augmenté.
L'utilisation de lamémoire lors de l'utilisation d'une solutionbasée sur untableau était d'environ 100 à 150 Moet a chuté à 20 Mo lors de l'exécution d'un SQL direct.
J'ai heurté unebosse avec la solution de @m0r7if3r quandj'aieubesoin depasser l'ID de suiveur à lafonction defiltreposts_where. Aumoins,àma connaissance,WordPressne permet aucunmoyen depasser une variable auxfonctions defichier. Vouspouvez cependant utiliser des variablesglobales,maisje voulais éviter lesglobales. J'aifini par étendre WP_Querypourenfin résoudre leproblème. Voici donc la solutionfinale quej'aiimplémentée (basée sur la solution de @m0r7if3r).
La classeclass WP_Query_Posts_by_Leader extends WP_Query { var $follower_id; function __construct($args=array()) { if(!empty($args['follower_id'])) { $this->follower_id = $args['follower_id']; add_filter('posts_where', array($this, 'posts_where')); } parent::query($args); } function posts_where($where) { global $wpdb; $table_name = $wpdb->prefix . 'follow'; $where .= $wpdb->prepare(" AND post_author IN (SELECT leader_id FROM " . $table_name . " WHERE follower_id = %d )", $this->follower_id); return $where; } } $args = array( 'post_type' => 'post', 'posts_per_page' => 10, 'follower_id' => $follower_id ); $wp_query = new WP_Query_Posts_by_Leader( $args );
Remarque:j'aifinalementessayé la solution ci-dessus avec 1,2million d'entrées dans letableau suivant. La duréemoyenne des requêtes était d'environ 0,060ms.
I am answering this question extremely late and my apologies for the same. I had been way too busy with deadlines to attend to this.
A big thanks to @m0r7if3r and @kaiser in providing the base solutions that I could extend and implement in my application. This answer provides details on my adaptation of the solutions offered by @m0r7if3r and @kaiser.
First, let me explain why this question was asked in the first place. From the question and the comments thereof one could gather that I am trying to get WP_Query to pull posts by all users (leaders) that a given user (follower) follows. The relationship between the follower and the leader is stored in a custom table
follow
. The most common solution to this problem is to pull the user ID's of the all leaders of a follower from the follow table and place it in an array. See below:global $wpdb; $results = $wpdb->get_results($wpdb->prepare('SELECT leader_id FROM cs_follow WHERE follower_id = %s', $user_id)); foreach($results as $result) $leaders[] = $result->leader_id;
Once you have the array of leaders you could pass it as an argument to WP_Query. See below:
if (isset($leaders)) $authors = implode(',', $leaders); // Necessary as authors argument of WP_Query only accepts string containing post author ID's seperated by commas $args = array( 'post_type' => 'post', 'posts_per_page' => 10, 'author' => $authors ); $wp_query = new WP_Query( $args ); // Normal WordPress loop continues
The above solution is the simplest way of achieving my desired results. However, it is non-scalable. The moment you have a follower following tens and thousands of leaders the resultant array of leader ID's would get extremely large and force your WordPress site to use 100MB - 250MB of memory on each page load and eventually crash the site. The solution to the problem is to run SQL query directly on the database and fetch relevant posts. That's when @m0r7if3r's solution came to rescue. Following @kaiser's recommendation I set out to test both implementations. I imported around 47K users from a CSV file to register them on a fresh test install of WordPress. The install was running Twenty Eleven theme. Following this I ran a for loop to make about 50 users follow every other user. The difference in query time for both @kaiser and @m0r7if3r's solution was staggering. @kaiser's solution normally took about 2 to 5 secs for each query. The variation I presume happens as WordPress caches queries for later use. On the other hand @m0r7if3r's solution demonstrated query time of 0.02 ms on average. For testing both solutions I had indexing ON for the leader_id column. Without indexing there was a dramatic increase in the query time.
The memory usage when using array based solution stood around 100-150 MB and dropped to 20 MB when running a direct SQL.
I hit a bump with @m0r7if3r's solution when I needed to pass the follower ID to the posts_where filter function. Atleast, as per my knowledge WordPress allows no means of passing a variable to filer functions. You can use Global variables though, but I wanted to avoid globals. I ended up extending WP_Query to finally address the issue. So here is the final solution I implemented (based on @m0r7if3r 's solution).
class WP_Query_Posts_by_Leader extends WP_Query { var $follower_id; function __construct($args=array()) { if(!empty($args['follower_id'])) { $this->follower_id = $args['follower_id']; add_filter('posts_where', array($this, 'posts_where')); } parent::query($args); } function posts_where($where) { global $wpdb; $table_name = $wpdb->prefix . 'follow'; $where .= $wpdb->prepare(" AND post_author IN (SELECT leader_id FROM " . $table_name . " WHERE follower_id = %d )", $this->follower_id); return $where; } } $args = array( 'post_type' => 'post', 'posts_per_page' => 10, 'follower_id' => $follower_id ); $wp_query = new WP_Query_Posts_by_Leader( $args );
Note: I eventually tried the above solution with 1.2 million entries in the follow table. The average query time stood around 0.060 ms.
-
Jene vous aijamais dit à quelpointj'ai apprécié la discussion sur cette question.Maintenant quej'ai découvert queje l'avaismanqué,j'ai ajouté un votepositif :)I never told you how much I appreciated the discussion on this question. Now that I found out that I missed it, I have add an upvote :)
- 3
- 2014-02-28
- kaiser
-
- 2012-04-26
Vouspouvez lefaire avec une solutionentièrement SQLen utilisant lefiltre
posts_where
. En voici unexemple:si (certaines conditions) add_filter ('posts_where','wpse50305_leader_where'); //lol,l'id de la questionest lemêmeen avantet en arrière function wpse50305_leader_where ($ où) { $ where.=$ GLOBALS ['wpdb'] - >prepare ('ANDpost_author'. 'DANS ( '. 'SELECT leader_id'. 'FROMnom_table_personnalisé'. 'WHEREid_serveur=% s'. ')',$id_serveur); retourner $ où; }
Jepense qu'il y apeut-être unmoyen de lefaire avec
JOIN
aussi,maisje nepeuxpas letrouver. Je vais continuer àjouer avecet mettre àjour la réponse sije l'obtiens.Alternativement,comme le suggère @kaiser ,vouspouvez le diviseren deuxparties: obtenir les leaderset faire la requête. J'ai le sentiment que c'estpeut-êtremoinsefficace,mais c'est certainement la voie laplus compréhensible. Vous devreztester vous-même l'efficacitépour déterminer quelleméthodeest lameilleure,car les requêtes SQLimbriquéespeuvent être assez lentes.
À PARTIR DES COMMENTAIRES:
Vous devezmettre lafonction dans votre
functions.php
et faire leadd_filter ()
juste avant laméthodequery ()
deWP_Query
est appelé. Immédiatement après cela,vous devezremove_filter ()
afin que celan'affectepas les autres requêtes.You can do this with an entirely SQL solution using the
posts_where
filter. Here's an example of that:if( some condition ) add_filter( 'posts_where', 'wpse50305_leader_where' ); // lol, question id is the same forward and backward function wpse50305_leader_where( $where ) { $where .= $GLOBALS['wpdb']->prepare( ' AND post_author '. 'IN ( '. 'SELECT leader_id '. 'FROM custom_table_name '. 'WHERE follower_id = %s'. ' ) ', $follower_id ); return $where; }
I think there may be a way to do this with
JOIN
as well, but I cannot come up with it. I will keep playing with it and update the answer if I get it.Alternately, as @kaiser suggested, you can split it to two parts: getting the leaders and doing the query. I have a feeling this might be less efficient, but it's certainly the more understandable way to go. You would have to test the efficiency for yourself to determine which method is better, as nested SQL queries can get quite slow.
FROM THE COMMENTS:
You should put the function in your
functions.php
and do theadd_filter()
right before thequery()
method ofWP_Query
is called. Immediately following that, you shouldremove_filter()
so that it does not affect the other queries.-
Modification de votre Aet ajout de `prepare ()`.J'espère que lamodificationne vous dérangepas.Et oui: lesperformances doivent êtremesuréespar OP.Quoi qu'ilen soit:je pensetoujours que cela devrait être simplement usermetaet rien d'autre.Edited your A and added `prepare()`. Hope you don´t mind the edit. And yes: Performance _has_ to be measured by OP. Anyway: I still think this should be simply usermeta and nothing else.
- 1
- 2012-04-26
- kaiser
-
@m0r7if3r Merci d'avoiressayé une solution.Je viens depublier un commentaireen réponse à la réponse de kaiser,avec desinquiétudes sur d'éventuelsproblèmes d'évolutivité.Veuillezen tenir compte.@m0r7if3r Thx for trying a solution. I just posted a comment in reply to kaiser's answer, with concerns on possible scalability issues. Please do take it into consideration.
- 0
- 2012-04-26
- John
-
@kaiser Çane me dérangepas dutout,en faitj'apprécieplutôt ça :)@kaiser Don't mind in the least, in fact I rather appreciate it :)
- 1
- 2012-04-26
- mor7ifer
-
@m0r7if3r Merci.Avoir desgars comme vous dans la communautéestgénial :)@m0r7if3r Thanks. Having guys like you in community rocks :)
- 0
- 2012-04-26
- kaiser
-
@m0r7if3r Atesté celaet jetrouve que cela oblige WP_Query à renvoyertous lesmessages.Partous lesmessages,je veux dire,lesmessages detoustypes (messages,piècesjointes,page) detous les utilisateurs.Il s'agit du SQL qui `echo $ wp_query-> request;`génèrepour la requête `SQL_CALC_FOUND_ROWS cs_posts. * FROM cs_posts INNER JOIN cs_postmeta ON (cs_posts.ID=cs_postmeta.post BY_id) WHERE 1=1 GROUP BY cs_posts.ID.post_date DESC LIMIT 0,30`@m0r7if3r Was testing this out and I find that this makes WP_Query return all posts. By all posts I mean, posts of all types (posts, attachments, page) of all users. This is the SQL that `echo $wp_query->request;` outputs for the query `SQL_CALC_FOUND_ROWS cs_posts.* FROM cs_posts INNER JOIN cs_postmeta ON (cs_posts.ID = cs_postmeta.post_id) WHERE 1=1 GROUP BY cs_posts.ID ORDER BY cs_posts.post_date DESC LIMIT 0, 30`
- 0
- 2012-04-26
- John
-
J'ai oublié de «return $ where;».Le codemis àjour corrige-t-il leproblème?I forgot to `return $where;`. Does the updated code correct the issue?
- 0
- 2012-04-26
- mor7ifer
-
Pouah!lesfautes defrappe.Oui,çamarchemaintenant.J'essaieraismaintenant demettreen œuvre la solution de @kaiseret demesurer les délais.BTW,uneffet secondaire queje vois de l'utilisation de ceciest queje commence à affectertoutes les requêtes s'il yen aplusieurs sur une seulepage.Deplus,cela a cassé les réécritures d'URLpourmoi lorsqu'ilestplacé dansfunction.php.Le déplacement du codejuste au-dessus de l'appel WP_Query a éliminé l'interférence avec les réécritures d'URL.Mais vousne savezpas si leplacer au-dessus de WP_Query serait unemauvaisepratique???Ugh! the typos. Yes, it works now. Would now try implementing @kaiser 's solution and measure the timings. BTW, a side effect I see of using this is that I starts affecting all queries if there are multiples of them on a single page. Additionally, this broke the URL rewrites for me when placed in function.php. Moving the code right above the WP_Query call cleared the interference with URL rewrites. Though not sure if placing it above WP_Query would be a bad practice???
- 0
- 2012-04-26
- John
-
Vous devriezmettre lafonction dans votre `functions.php`et faire le` add_filter () `juste avant que laméthode` query () `de` WP_Query` soit appelée.Immédiatement après cela,vous devriez `remove_filter ()`pour que celan'affectepas les autres requêtes.Jene saispas quel serait leproblème avec la réécriture d'URL,j'ai utilisé `posts_where` àplusieurs repriseset jen'aijamais vu cela ...You should put the function in your `functions.php` and do the `add_filter()` right before the `query()` method of `WP_Query` is called. Immediately following that, you should `remove_filter()` so that it does not affect the other queries. I'm not sure what the issue with URL rewriting would be, I've used `posts_where` on many occasions and never seen that...
- 1
- 2012-04-26
- mor7ifer
-
@m0r7if3r Merci d'avoir souligné cela.Passons auxtests sur lesexemples de données.Voustiendrons au courant.@m0r7if3r Thx for pointing that out. Moving on with the tests on the sample data. Will keep you posted.
- 0
- 2012-04-26
- John
-
@m0r7if3r Votre dernier commentaireferait unebonne citation à l'intérieur du Q :)@m0r7if3r Your last comment would make a good quote inside the Q :)
- 0
- 2012-04-27
- kaiser
-
C'est certainement lameilleure solution.Bienjoué!This is definitely the best solution. Well done!
- 0
- 2015-10-05
- Travis van der Font
-
- 2012-04-26
Balise demodèle
Placez simplement les deuxfonctions dans votrefichier
functions.php
. Puis ajustez la 1èrefonctionet ajoutez votrenom detablepersonnalisé. Ensuite,vous avezbesoin d'unessai/erreurpour vous débarrasser de l'ID utilisateur actuel dans letableau résultant (voir commentaire)./** * Get "Leaders" of the current user * @param int $user_id The current users ID * @return array $query The leaders */ function wpse50305_get_leaders( $user_id ) { global $wpdb; return $wpdb->query( $wpdb->prepare( " SELECT `leader_id`, `follower_id` FROM %s WHERE `follower_id` = %s ORDERBY `leader_id` ASC ", // Edit the table name "{$wpdb->prefix}custom_table_name" $user_id ) ); } /** * Get posts array that contain posts by * "Leaders" the current user is following * @return array $posts Posts that are by the current "Leader */ function wpse50305_list_posts_by_leader() { get_currentuserinfo(); global $current_user; $user_id = $current_user->ID; $leaders = wpse5035_get_leaders( $user_id ); // could be that you need to loop over the $leaders // and get rid of the follower ids return get_posts( array( 'author' => implode( ",", $leaders ) ) ); }
À l'intérieur dumodèle
Ici,vouspouvezfaire ce que vous voulez avec vos résultats.
foreach ( wpse50305_list_posts_by_leader() as $post ) { // do something with $post }
REMARQUE Nous n'avons pas de données detest,etc. donc ce quiprécèdeest unpeu unjeu de devinettes. Assurez-vous que vous modifiez cette réponse avec ce qui afonctionnépour vous,afin quenous ayons un résultat satisfaisantpour les lecteurs ultérieurs. J'approuverai lamodification au cas où vous auriez une réputationtropfaible. Vouspouvez alors également supprimer cettenote. Merci.
Template Tag
Just place both functions in your
functions.php
file. Then adjust the 1st function and add your custom table name. Then you need some try/error to get rid of the current user ID inside the resulting array (see comment)./** * Get "Leaders" of the current user * @param int $user_id The current users ID * @return array $query The leaders */ function wpse50305_get_leaders( $user_id ) { global $wpdb; return $wpdb->query( $wpdb->prepare( " SELECT `leader_id`, `follower_id` FROM %s WHERE `follower_id` = %s ORDERBY `leader_id` ASC ", // Edit the table name "{$wpdb->prefix}custom_table_name" $user_id ) ); } /** * Get posts array that contain posts by * "Leaders" the current user is following * @return array $posts Posts that are by the current "Leader */ function wpse50305_list_posts_by_leader() { get_currentuserinfo(); global $current_user; $user_id = $current_user->ID; $leaders = wpse5035_get_leaders( $user_id ); // could be that you need to loop over the $leaders // and get rid of the follower ids return get_posts( array( 'author' => implode( ",", $leaders ) ) ); }
Inside the template
Here you can do whatever you want with your results.
foreach ( wpse50305_list_posts_by_leader() as $post ) { // do something with $post }
NOTE We don´t have testdata, etc. so the above is a little bit of a guessing game. Make sure that you edit this answer with what worked for you, so we have a satisfying result for later readers. I´ll approve the edit in case you got too low rep. You then can also delete this note. Thanks.
-
Merci d'avoirfourni une solution.Cependant,cette approche comporte desmisesen gardeen termes d'évolutivité.Leproblèmeest de récupérer l'identifiant des leaders sousforme detableau.Letableaupeut devenirextrêmement volumineuxen fonction dunombre d'utilisateurs suivispar un utilisateur.J'ai vu cela consommer unegrande quantité demémoire.Cela doit êtrefaiten tant que requête SQL unique quipeutimpliquer d'effectuer unejointure sur latablepersonnaliséeet latable despublications WPet de récupérer les résultats.Lameilleure solution consiste à étendre WP_Query.Leproblème,je ne saispas commentfaire.Encore unefoismerci d'avoiressayé.Les commentaires sont lesbienvenus.Thx for providing a solution. However, this approach has caveats in terms of scalability. The problem is in fetching the id of leaders as an array. The array could get extremely large depending on the number of users a user follows. I have seen this consume large amount of memory. This needs to be done as a single SQL query which might involve performing a join on the custom table & WP posts table and fetching the results. The best solution is to extend WP_Query. The problem, I don't know how to do it. Again thx for attempting. Feedbacks welcome.
- 0
- 2012-04-26
- John
-
«JOIN»est **beaucoupplus ** cher.** Plus: ** Commeje l'aimentionné,nousn'avonspas de données detest,veuillez donctester les deux réponseset nous éclairer avec vos résultats.`JOIN` is **much more** expensive. **Plus:** As I mentioned, we don´t have test data, so please test both answers and enlighten us with your results.
- 2
- 2012-04-26
- kaiser
-
WP_Query lui-mêmefonctionne avec les JOINentre latable despublicationset postmeta lors de l'interrogation.J'ai vu l'utilisation de lamémoire PHPpasser à 70 Mo - 200 Mopar chargement depage.Exécuter quelque chose comme ça avec denombreux utilisateurs simultanésnécessiterait uneinfrastructureextrême.Je suppose quepuisque WordPressimplémente déjà unetechnique similaire,les JOINs devraient êtremoins éprouvants que detravailler avec untableau d'ID.WP_Query itself works with JOINs between posts table and postmeta when querying. I have seen PHP memory usage bump to 70MB - 200MB per page load. Running something like that with many simultaneous users would require an extreme infrastructure. My guess would be that since, WordPress already implements similar technique, JOINs should be less taxing in comparison to working with array of ID's.
- 1
- 2012-04-26
- John
-
Non,sry,maisnon.Il y a aussi destentatives de se débarrasser des `JOIN`s supplémentaires.Exemple: WP ajoute un `JOIN` de latable determes lors de la recherche deplusieurstaxonomies qui sont contre-performantes.Utilisez simplement [`timer_start ()`] (http://codex.wordpress.org/Function_Reference/timer_start) avant la requêteet [`timer_stop ()`] (http://codex.wordpress.org/Function_Reference/timer_stop)après la requêtepourmesurer la différence.No, sry, but no. There´re also tries to get rid of additional `JOIN`s. Example: WP is adding a `JOIN` of the term table when querying for multiple taxonomies which is counter-performant. Just use [`timer_start()`](http://codex.wordpress.org/Function_Reference/timer_start) before the query and [`timer_stop()`](http://codex.wordpress.org/Function_Reference/timer_stop) after the query to measure the difference.
- 0
- 2012-04-26
- kaiser
-
** Plus: ** Assurez-vous que vous avez l'INDEX sur la colonne de droite.Celafait une énorme différence deperformances.Dans unprojet quej'ai réalisé,oùje devaisfaire des requêtespour lat/lng,j'ai unetable supplémentaire quiestpetite,bien indexéeet exécute _beaucoup_plus vite que _toutes_ `JOIN` quej'aiessayé.Pouren savoirplus sur les «JOIN»,lisez celui-ci] (http://stackoverflow.com/a/174047/376483).**Plus:** Make shure you have the `INDEX` on the right column. This makes a _huge_ difference in performance. In a project I made, where I needed to do queries for lat/lng, I have an additional table that small, well indexed and performs _much_ faster than _any_ `JOIN` I tried. For deeper [knowledge about `JOIN`s, read this one](http://stackoverflow.com/a/174047/376483).
- 0
- 2012-04-26
- kaiser
-
Oh,et oui,cela dépend aussi de _quel_ `JOIN` que vous utilisez ...Oh, and yeah, it also depends on _which_ `JOIN` you´re using...
- 0
- 2012-04-26
- kaiser
-
Donc,votre conseil serait de s'entenir à untableauplutôt que d'exécuter un SQL avec unejointure correcte?So your advice would be to stick with array than running a SQL with join correct?
- 0
- 2012-04-26
- John
-
Oui,mais comme @m0r7if3r l'a dit: Mesurez-le.Je vous ai donné les liens.Il vous suffit de le chronométreret denousmontrer ce que vousen avez retiré.Si vousne lefaitespas,ehbien,nous avonsfaitbeaucoup debelles suppositions :)Yes, but as @m0r7if3r said: Measure it. I gave you the links. You just have to time it and show us what you got out of it. If you don´t do it, well then we have done a lot of nice _guessing_ :)
- 0
- 2012-04-26
- kaiser
-
J'essaye certainement les deux solutions.Mais,pour chronométrer cela,je devrai vider labase de données avec les données detest,ce quiprendra quelques heures (remplira labase de données avec 50k utilisateurs).Feraet voustiendra au courant.I am certainly trying out both solutions. But, for timing this I'll have to dump the database with test data which will take few hours (will populate the db with 50k users). Will do and keep you posted.
- 0
- 2012-04-26
- John
-
@John c'estbon àentendre.veulent vraiment connaître la sortie.@John good to hear. really want to know the outcoming.
- 1
- 2012-04-26
- kaiser
-
Ok,voici les résultats dutest.Pour cela,j'ai ajoutéenviron 47K utilisateurs àpartir d'unfichier csv.Plustard,aexécuté uneboucleforpour que les 45premiers utilisateurs suiventtous les autres utilisateurs.Cela a abouti à 3 704 951enregistrementsenregistrés dansmatablepersonnalisée.Initialement,la solution de @m0r7if3rm'a donné untemps de requête de 95 secondes,quiest descendu à 0,020ms après l'activation de l'indexation sur la colonne leader_id.Lamémoire PHPtotale consommée était d'environ 20 Mo.D'autrepart,votre solution aprisenviron 2 à 5 secondespour la requête avec l'indexation activée.Lamémoire PHPtotale consommée était d'environ 117 Mo.Ok here are the test results. For this I added about 47K users from a csv file. Later, ran a for loop to make the first 45 users follow every other user. This resulted in 3,704,951 records saved to my custom table. Initially, @m0r7if3r 's solution gave me query time of 95 secs, which went down to 0.020 ms after turning ON indexing on leader_id column. The total PHP memory consumed was around 20MB. On the other hand, your solution took about 2 to 5 secs for query with indexing ON. The total PHP memory consumed was around 117MB.
- 4
- 2012-04-27
- John
-
@John Pourriez-vous s'il vousplaît ajouter ceci comme réponse séparée?Vraiment heureux que vous ayezfait cetestet que vousnous ayezfourni des données _real_.:) Ce quej'apprécieraisencoreplus,c'est untestplus "réel": laissez chaque utilisateur suivre un `$ leader_amount=rand (0,5);`puis ajoutez lenombre de `$ leader_amount` x` $ random_ids=rand (0,47000); `à chaque utilisateur.Jusqu'àprésent,la chose quenous savonsest la suivante:ma solution seraitextrêmementmauvaise si un utilisateur suit _chaque_ autre utilisateur.Deplus: Vous aurez àmontrer _comment_ vous avezfait letestet _oùexactement_ vous avez ajouté lesminuteries.C'est un Q uniqueet j'aime vraiment ça :)@John Could you please add this as separate answer? Really glad, that you made this test and provided us with _real_ data. :) What I`d appreciate even more is a more "real life" test: Let every user follow a `$leader_amount = rand( 0, 5 );` and then add the number of `$leader_amount` x `$random_ids = rand( 0, 47000 );` to each user. So far the thing we know is: My solution would be extremly bad if a user is following _each_ other user. Further: You´ll have show _how_ you did the test and _where exactly_ you added the timers. This is a one time Q and I really like it :)
- 0
- 2012-04-27
- kaiser
-
@John J'ai liéet transmis votre questionet votreparticipationet je voulaisnoter quetout lemonde appréciebeaucoup votretravail (voir les votespositifs).:)@John I linked and passed around your Q and participation and wanted to note that everyone is highly enjoying your work on it (see upvotes). :)
- 0
- 2012-04-27
- kaiser
-
Je vaistester davantageen fonction de votre suggestionpoureffectuer untestplus réelet ensuite écrire une réponse avec des détails.Cependant,pour un vraitest de la vie réelle,il y a deux autres variables queje nepeux actuellementpas simuler.Un: Alteast,20messagespar chaque utilisateur.Actuellement,je n'aitesté qu'avecenviron 50messagesentre 2-3 utilisateurs.Deuxièmement: untraficimportant.Ces deux variables auraient également unimpact sur les résultats obtenus dans la vie réelle.I'll further test based on your suggestion to perform a more real life test and subsequently write an answer with details. However, for a true real life test there are two other variables that I currently cannot simulate. One: Alteast, 20 posts by every user. Currently, I only tested with about 50 posts between 2-3 users. Second: A large traffic. These two variables would also impact the results obtained in real life.
- 0
- 2012-04-27
- John
-
Étudieplusen détail votre suggestion de randomiser les éléments suivants.Cependant,je n'aipaspu comprendre lesfragments de code que vous avez écrits.Unextrait complet seraitplus utile.C'est ce quej'avaisfaitpour que les 50premiers utilisateurs se suivent: `for ($j=2; $j <=52; $j ++) {for ($i=($j + 1); $i <=47000; $i ++) {$ rows_affected=$ wpdb->insert ($nom_table,array ('leader_id'=> $i,'follower_id'=> $j));}} `.Uneboucleforimbriquéetrès simple.Was further looking into your suggestion to randomize the following. However, I could not understand the code fragments you wrote. A complete snippet would be more helpful. This is what I had done to make first 50 user follow every other: `for ($j = 2; $j <= 52; $j++) { for ($i = ($j + 1); $i <= 47000; $i++) { $rows_affected = $wpdb->insert($table_name, array( 'leader_id' => $i, 'follower_id' => $j)); } }`. A very simple nested for loop.
- 0
- 2012-04-27
- John
-
Àpropos dutrafic) Vouspouvez utiliser les derniers apache,nginx,la réduction,lamiseen cache,la compression,etc. Chacun aurait unimpact sur les résultats.Maisnous recherchons les résultats dans un résultat local,simple (sansplug-in,thèmepar défaut) quipeut _ vraiment_ êtrepondéré.About traffic) You could use the latest apache, nginx, minifying, caching, compression, etc. Each would have an impact on the results. But we are after the results in a local, plain vanilla (no-plugins, default theme) result that can _really_ be weightened.
- 0
- 2012-04-27
- kaiser
-
Avez-vous reçu unenotificationpourmon commentaire concernant la randomisation suivante?Je suppose quej'ai oublié dementionner votrepoignée dans le commentaire.Néanmoins,je suppose que lepropriétaire dumessageest averti.J'attendrais vosentrées avant de continuer.Did you receive a notification for my comment in regards to following randomization? I guess I forgot mention your handle in the comment. Nonetheless, I guess the post owner is notified. Would wait for your inputs before proceeding.
- 0
- 2012-04-27
- John
-
J'ajoute une autre réponse (nouspouvonstraiteret modifier/éditer là-dessus) car leformatage du code dans les commentairesesttout simplementnul: PI add another answer (we can process & modify/edit on that) as code formatting in comments simply sucks :P
- 1
- 2012-04-28
- kaiser
-
- 2012-04-28
Remarque: Cette réponseesticipour éviter une discussionprolongée dans les commentaires
-
Voici le code des OP àpartir des commentaires,pour ajouter lepremierensemble d'utilisateurs detest. Je dois êtremodifiépour unexemple dumonde réel.
for ( $j = 2; $j <= 52; $j++ ) { for ( $i = ($j + 1); $i <= 47000; $i++ ) { $rows_affected = $wpdb->insert( $table_name, array( 'leader_id' => $i, 'follower_id' => $j ) ); } }
OP Àpropos dutest Pour cela,j'ai ajoutéenviron 47K utilisateurs àpartir d'unfichier csv. Plustard,aexécuté uneboucleforpour que les 45premiers utilisateurs suiventtous les autres utilisateurs.
- Cela a abouti à 3 704 951enregistrementsenregistrés dansmatablepersonnalisée.
- Au départ,la solution de @m0r7if3rm'a donné untemps de requête de 95 secondes,quiestpassé à 0,020ms après l'activation de l'indexation sur la colonne leader_id. Lamémoire PHPtotale consommée était d'environ 20 Mo.
- D'autrepart,votre solution aprisenviron 2 à 5 secondespour la requête avec l'indexation activée. Lamémoire PHPtotale consommée était d'environ 117 Mo.
-
Ma réponse à ce ↑test:
untestplus "réel": laissez chaque utilisateur suivre un
$leader_amount = rand( 0, 5 );
puis ajoutez lenombre de$leader_amount x $random_ids = rand( 0, 47000 );
à chaque utilisateur. Jusqu'àprésent,la chose quenous savonsest la suivante:ma solution seraitextrêmementmauvaise si un utilisateur se suit les uns les autres. Deplus: vous devrezmontrer comment vous avezfait letestet oùexactement vous avez ajouté lesminuteries.Je dois aussi déclarer que le suivi dutemps ↑ ci-dessusne peutpas être vraimentmesuré,carilfaudrait aussi dutempspour calculer laboucleensemble. Lemieux serait deparcourir l'ensemble d'identifiants résultant dans une deuxièmeboucle.
processus supplémentaireici
Note: This answer here is to avoid extended discussion in the comments
Here´s the OPs Code from the comments, to add the first set of test users. I has to be modified to a real world example.
for ( $j = 2; $j <= 52; $j++ ) { for ( $i = ($j + 1); $i <= 47000; $i++ ) { $rows_affected = $wpdb->insert( $table_name, array( 'leader_id' => $i, 'follower_id' => $j ) ); } }
OP About Test For this I added about 47K users from a csv file. Later, ran a for loop to make the first 45 users follow every other user.
- This resulted in 3,704,951 records saved to my custom table.
- Initially, @m0r7if3r 's solution gave me query time of 95 secs, which went down to 0.020 ms after turning ON indexing on leader_id column. The total PHP memory consumed was around 20MB.
- On the other hand, your solution took about 2 to 5 secs for query with indexing ON. The total PHP memory consumed was around 117MB.
My answer to this ↑ test:
a more "real life" test: Let every user follow a
$leader_amount = rand( 0, 5 );
and then add the number of$leader_amount x $random_ids = rand( 0, 47000 );
to each user. So far the thing we know is: My solution would be extremly bad if a user is following each other user. Further: You´ll have show how you did the test and where exactly you added the timers.I also have to state that the ↑ above time tracking can´t be really measured, as it would also take the time to compute the loop together. Better would be to loop through the resulting set of IDs in a second loop.
further process here
-
Remarquepour ceux qui ont suivi cette Q: Je suisen train demesurer lesperformances dans diverses conditionset publierai le résultat dans unjour ou 3. Cettetâche a étéextrêmement longueen raison de l'échelle des données detest qui doivent êtregénéré.Note for those who have been following this Q: I am in process of measuring the performance under various conditions and will post the result in a day or 3. This has been extremely time consuming task due to the scale of test data that need to be generated.
- 2
- 2012-04-30
- John
Celafait desjours queje parle de ceproblème. Au départ,il s'agissait de savoir comment stocker les données d'abonné d'un utilisateur dans unebase de données,pour laquellej'ai reçu quelquesbonnes recommandationsici sur WordPress Answers. Après,en suivant les recommandations,j'ai ajouté unnouveautableau comme celui-ci:
Dans letableau ci-dessus,lapremière ligne a un utilisateur avec un ID de 2 quiest suivipar un utilisateur avec un ID de 4. Dans la deuxième ligne,un utilisateur avec un ID de 3est suivipar un utilisateur avec un ID de 10. Lamême logique s'appliquepour latroisième ligne.
Maintenant,je veuxessentiellement étendre WP_Query afin queje puisse limiter lesmessages récupérés à celui de,uniquementpar le (s) chef (s) d'un utilisateur. Donc,en tenant compte dutableau ci-dessus,sije devaistransmettre l'ID utilisateur 10 à WP_Query,les résultatsne devraient contenir que lespublicationspar ID utilisateur 2et ID utilisateur 3.
J'aibeaucoup cherchépouressayer detrouver une réponse. Demême,je n'ai vu aucuntutorielpourm'aider à comprendre comment étendre la classe WP_Query. J'ai vu les réponses de Mike Schinkel (étendant WP_Query) à des questions similaires,maisje n'ai vraimentpas compris comment l'appliquer àmesbesoins. Ce seraitformidable si quelqu'unpouvaitm'aider avec ça.
Liens vers les réponses de Mike comme demandé: Lien 1 , Lien 2