WP Query Args - Titlu sau Valoare Meta

18 feb. 2015, 02:59:25
Vizualizări: 22.2K
Voturi: 12

Cum pot face o interogare după meta_value sau titlu?

Dacă setez meta_values,

$args['meta_query'] = array(
   'relation' => 'OR',
    array(
        'key' => 'model_name',
        'value' => $thesearch,
        'compare' => 'like'
    )
);

acestea sunt adăugate automat ca AND.

Această căutare ar fi:

WHERE title = 'Search' AND (model_name = 'Search' OR ...)

Am nevoie de

WHERE title = 'Search' OR (model_name = 'Search' OR ...)
1
Comentarii

Am încercat să adaug $args['relation'] = 'OR'; Dar, nu este recunoscut. Se pare că nu înțeleg cum să controlez logica condițională prin args.

Bryan Bryan
18 feb. 2015 03:04:49
Toate răspunsurile la întrebare 3
16
28

Rețineți că partea relation din argumentul meta_query este folosită doar pentru a defini relația între sub interogările meta.

Puteți încerca această configurație:

$args = [ 
    '_meta_or_title' => $thesearch,   // Argumentul nostru personalizat nou!
    'meta_query'    => [
        [
            'key'     => 'model_name',
            'value'   => $thesearch,
            'compare' => 'like'
        ]
    ],
];

unde am introdus un argument personalizat _meta_or_title pentru a activa interogarea meta SAU titlu.

Aceasta este susținută de următorul plugin:

<?php
/**
 *  Plugin Name:   Interogare Meta SAU Titlu în WP_Query
 *  Description:   Activă prin argumentul '_meta_or_title' al WP_Query 
 *  Plugin URI:    http://wordpress.stackexchange.com/a/178492/26350
 *  Plugin Author: Birgir Erlendsson (birgire)
 *  Version:       0.0.1
 */

add_action( 'pre_get_posts', function( $q )
{
    if( $title = $q->get( '_meta_or_title' ) )
    {
        add_filter( 'get_meta_sql', function( $sql ) use ( $title )
        {
            global $wpdb;

            // Rulează doar o singură dată:
            static $nr = 0; 
            if( 0 != $nr++ ) return $sql;

            // Modifică partea WHERE:
            $sql['where'] = sprintf(
                " AND ( %s OR %s ) ",
                $wpdb->prepare( "{$wpdb->posts}.post_title = '%s'", $title ),
                mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
            );
            return $sql;
        });
    }
});
18 feb. 2015 07:12:24
Comentarii

Wow. Răspuns minunat! Ar trebui să fie inclus în nucleu.

Bryan Bryan
18 feb. 2015 22:06:29

Răspunsul m-a ajuns pe jumătate. http://wordpress.stackexchange.com/questions/178574/acf-relationship-field-search-filtering Ai vreo idee pentru următoarea problemă?

Bryan Bryan
18 feb. 2015 22:16:36

Am folosit acest răspuns pentru a crea o interogare pentru o valoare meta specifică pe pagina edit.php pentru un tip de postare personalizat. Nu interoghez deloc titlul, deoarece tipul meu de postare personalizat nu are titlu. Prin urmare, am înlocuit " AND ( %s OR %s ) " cu " OR ( %s ) " în interogarea SQL și am eliminat complet linia $wpdb->prepare( "{$wpdb->posts}.post_title = '%s'", $title ),. Este aceasta o abordare validă?

BdN3504 BdN3504
17 mai 2015 13:30:57

@BdN3504 Mă bucur să aud că ți s-a părut oarecum util. Dacă te-am înțeles corect, modificările tale ar trebui să funcționeze.

birgire birgire
17 mai 2015 16:20:48

mulțumesc pentru răspuns. modificările mele funcționează, dar nu sunt sigur dacă este abordarea corectă. de fapt, vreau să scap de parametrii de titlu și conținut din interogare și să interoghez doar meta. deși abordarea actuală funcționează, nu este cea mai practică

BdN3504 BdN3504
17 mai 2015 22:32:03

@BdN3504 ok grozav, nu știu de o metodă nativă (fără a folosi filtre) pentru a schimba AND -> OR pentru întreaga interogare meta, dar poți modifica relațiile interogării meta în multe feluri în cadrul meta_query din WP_Query.

birgire birgire
17 mai 2015 22:40:43

Truc excelent. Dacă dorești să cauți un subșir în titlu, înlocuiește post_title = '%s' cu post_title like '%%%s%%'.

jarnoan jarnoan
30 sept. 2015 13:11:47

Cum aș putea executa o interogare cu titlul și valoarea taxonomiei în loc de valoarea meta?

Jeff Jeff
13 oct. 2018 18:11:23

@jeff Am scris odată un plugin pentru a combina interogări: https://github.com/birgire/wp-combine-queries. De asemenea, aici am experimentat cu căutarea (titlu, rezumat, conținut) sau interogarea taxonomiei. Aici am găsit un alt răspuns similar cu care am experimentat. De asemenea, putem scrie două interogări WP_Query separate, apoi colecta și combina ID-urile postărilor rezultate într-o a treia interogare WP_Query (dacă este necesar și dacă ordonarea PHP nu este suficientă) prin parametrul de intrare post__in.

birgire birgire
13 oct. 2018 20:39:24

@birgire Am ales calea cu două interogări separate și a funcționat, mulțumesc.

Jeff Jeff
13 oct. 2018 22:39:17

@Jeff Mă bucur că a funcționat pentru tine.

birgire birgire
13 oct. 2018 22:42:18

@biergie Mulțumesc pentru această soluție minunată! Funcționează excelent, dar căutarea mea nu returnează niciun rezultat când folosesc _meta_or_title + meta query + tax query. Când utilizez filtrul tău personalizat și adaug un tax_query, elementul $sql['where'] este gol. Ai vreo idee cum să rezolv asta?

chris.ribal chris.ribal
6 iun. 2019 15:50:42

@biergie Mulțumesc. Nu am testat de ceva vreme, dar ar trebui să te asiguri că nu există alte plugin-uri/cod care să afecteze acest lucru și, de exemplu, să rulezi cu depanarea activată.

birgire birgire
7 iun. 2019 13:05:50

@birgire - doar mă întrebam dacă tu sau cineva puteți să indicați unde folosiți $args? mulțumesc.

v3nt v3nt
29 iun. 2020 19:48:55

$q->get( '_meta_or_title' ) este la fel ca $args['_meta_or_title'].

birgire birgire
30 iun. 2020 15:01:01

Soluție spectaculoasă! Sugerez să editezi pentru a include comentariul lui jarnoan despre folosirea LIKE în loc de =, deoarece este un sfat foarte util, dar ușor de trecut cu vederea.

Kai Qing Kai Qing
22 oct. 2020 05:53:00
Arată celelalte 11 comentarii
1

Nu am găsit o soluție pentru a căuta mai multe cuvinte cheie care pot fi amestecate fie în titlul postării, descriere ȘI/SAU una sau mai multe metadate, așa că am creat propria mea adăugare la funcția de căutare.

Tot ce trebuie să faci este să adaugi următorul cod în function.php, și ori de câte ori folosești argumentul 's' în WP_Query() și vrei să caute și în una sau mai multe metadate, pur și simplu adaugi un argument 's_meta_keys' care este un array cu cheile meta în care dorești să cauți:

/************************************************************************\
|**                                                                    **|
|**  Permite funcției de căutare WP_Query() să caute mai multe         **|
|**  cuvinte cheie în metadate în plus față de post_title și           **|
|**  post_content                                                      **|
|**                                                                    **|
|**  De rAthus @ Arkanite                                             **|
|**  Creat: 2020-08-18                                                **|
|**  Actualizat: 2020-08-19                                           **|
|**                                                                    **|
|**  Folosește argumentul obișnuit 's' și adaugă un argument           **|
|**  's_meta_keys' conținând un array cu cheile meta în care           **|
|**  dorești să cauți :)                                              **|
|**                                                                    **|
|**  Exemplu :                                                        **|
|**                                                                    **|
|**  $args = array(                                                   **|
|**      'numberposts'  => -1,                                        **|
|**      'post_type' => 'post',                                       **|
|**      's' => $MY_SEARCH_STRING,                                    **|
|**      's_meta_keys' => array('META_KEY_1','META_KEY_2');           **|
|**      'orderby' => 'date',                                         **|
|**      'order'   => 'DESC',                                         **|
|**  );                                                               **|
|**  $posts = new WP_Query($args);                                    **|
|**                                                                    **|
\************************************************************************/
add_action('pre_get_posts', 'my_search_query'); // adaugă funcția specială de căutare la fiecare interogare get_posts (asta include WP_Query())
function my_search_query($query) {
    if ($query->is_search() and $query->query_vars and $query->query_vars['s'] and $query->query_vars['s_meta_keys']) { // dacă căutăm folosind argumentul 's' și am adăugat un argument 's_meta_keys'
        global $wpdb;
        $search = $query->query_vars['s']; // obține șirul de căutare
        $ids = array(); // inițializează array-ul de ID-uri de postări potrivite per cuvânt cheie căutat
        foreach (explode(' ',$search) as $term) { // despachetează cuvintele cheie și caută rezultate potrivite pentru fiecare
            $term = trim($term); // elimină spațiile inutile
            if (!empty($term)) { // verifică dacă cuvântul cheie nu este gol
                $query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status='publish' AND ((post_title LIKE '%%%s%%') OR (post_content LIKE '%%%s%%'))", $term, $term); // caută în titlu și conținut ca funcția normală
                $ids_posts = [];
                $results = $wpdb->get_results($query_posts);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_posts[] = $result->ID; // adună ID-urile postărilor potrivite
                $query_meta = [];
                foreach($query->query_vars['s_meta_keys'] as $meta_key) // acum construiește o interogare de căutare pentru fiecare cheie meta dorită
                    $query_meta[] = $wpdb->prepare("meta_key='%s' AND meta_value LIKE '%%%s%%'", $meta_key, $term);
                $query_metas = $wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE ((".implode(') OR (',$query_meta)."))");
                $ids_metas = [];
                $results = $wpdb->get_results($query_metas);
                if ($wpdb->last_error)
                    die($wpdb->last_error);
                foreach ($results as $result)
                    $ids_metas[] = $result->post_id; // adună ID-urile postărilor potrivite
                $merged = array_merge($ids_posts,$ids_metas); // combină ID-urile din titlu, conținut și metadate rezultate din ambele interogări
                $unique = array_unique($merged); // elimină duplicatele
                if (!$unique)
                    $unique = array(0); // dacă nu sunt rezultate, adaugă un ID "0" altfel vor fi returnate toate postările
                $ids[] = $unique; // adaugă array-ul de ID-uri potrivite în array-ul principal
            }
        }
        if (count($ids)>1)
            $intersected = call_user_func_array('array_intersect',$ids); // dacă sunt mai multe cuvinte cheie, păstrează doar ID-urile găsite în toate array-urile de potriviri
        else
            $intersected = $ids[0]; // altfel păstrează array-ul unic de ID-uri potrivite
        $unique = array_unique($intersected); // elimină duplicatele
        if (!$unique)
            $unique = array(0); // dacă nu sunt rezultate, adaugă un ID "0" altfel vor fi returnate toate postările
        unset($query->query_vars['s']); // elimină interogarea normală de căutare
        $query->set('post__in',$unique); // adaugă un filtru după ID-ul postării în schimb
    }
}

Exemplu de utilizare:

$search= "cuvinte cheie pentru căutare";

$args = array(
    'numberposts'   => -1,
    'post_type' => 'post',
    's' => $search,
    's_meta_keys' => array('short_desc','tags');
    'orderby' => 'date',
    'order'   => 'DESC',
);

$posts = new WP_Query($args);

Acest exemplu va căuta cuvintele cheie "cuvinte cheie pentru căutare" în titlurile postărilor, descrieri și cheile meta 'short_desc' și 'tags'.

Cuvintele cheie pot fi găsite într-unul sau mai multe dintre câmpuri, în orice ordine, va returna orice postare care are toate cuvintele cheie în oricare dintre câmpurile desemnate.

Poți evident forța căutarea într-o listă de chei meta pe care le incluzi în funcție și să scapi de argumentele suplimentare dacă vrei ca TOATE interogările de căutare să includă aceste chei meta :)

Sper că acest lucru va ajuta pe oricine se confruntă cu aceeași problemă ca mine!

18 aug. 2020 21:01:43
Comentarii

Pare destul de solid. Poți ajuta încercând să incluzi câmpuri personalizate de la autorul unui articol [utilizator]?

Adeerlike Adeerlike
30 mar. 2022 15:39:08
1

Sunt destul de nou în WordPress, nu am testat prea mult această abordare la care am ajuns. Poate mă puteți ajuta să verific dacă am dreptate. Soluția pe care am găsit-o până acum este să implementez aceeași logică meta_query, făcând câteva înlocuiri.

În primul rând, modul de utilizare:

$args = array(
    'lang' => 'pt', //această funcție nu intră în conflict (exemplu: polylang)
    'post_type' => 'produtos', 
    'post_status'   => 'publish',
    'posts_per_page' => 10,
    'paged' =>  1,
    'fields' => 'ids',
);
$args['meta_query] = [
    ['relation'] => 'OR'; //orice relație doriți
    [
        'key' => 'acf_field', //orice câmp personalizat (utilizare normală)
        'value' => $search, //orice valoare (utilizare normală)
        'compare' => 'LIKE', //orice comparație (utilizare normală)
    ],
    [
        'key' => 'post_title', //setați conținutul implicit al postării WordPress dorit ('post_content', 'post_title' și 'post_excerpt')
        'value' => $search, //orice valoare
        'compare' => 'LIKE', //testat cu 'LIKE' și '=', funcționează excelent și nu-mi pot imagina alte nevoi.
    ],
    [
        'key' => 'post_exerpt', //puteți adăuga de câte ori aveți nevoie
        'value' => $search_2,
        'compare' => 'LIKE', 
    ],
];
$the_query = new WP_Query( $args ); //doar interogare
wp_reset_postdata(); //curățați interogarea

Pentru a funcționa, adăugați această funcție în fișierul functions.php al temei dumneavoastră:

function post_content_to_meta_queries($where, $wp_query){
    global $wpdb;

    //dacă nu există metaquery, pa!
    $meta_queries = $wp_query->get( 'meta_query' );
    if( !$meta_queries || $meta_queries == '' ) return $where;

    //dacă există o singură relație
    $where = str_replace($wpdb->postmeta . ".meta_key = 'post_title' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_title", $where);
    $where = str_replace($wpdb->postmeta . ".meta_key = 'post_content' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_content", $where);
    $where = str_replace($wpdb->postmeta . ".meta_key = 'post_excerpt' AND " . $wpdb->postmeta . ".meta_value", $wpdb->posts . ".post_excerpt", $where);

    //pentru relații imbricate

    //numarați câte meta queries există pentru posibile înlocuiri
    $number_of_relations = count($meta_queries);

    //înlocuiți 'WHERE' folosind logica de denumire multidimensională a postmeta folosită de nucleul WordPress
    $i = 1;
    while($i<=$number_of_relations && $number_of_relations > 0){
        $where = str_replace("mt".$i.".meta_key = 'post_title' AND mt".$i.".meta_value", $wpdb->posts . ".post_title", $where);
        $where = str_replace("mt".$i.".meta_key = 'post_content' AND mt".$i.".meta_value", $wpdb->posts . ".post_content", $where);
        $where = str_replace("mt".$i.".meta_key = 'post_excerpt' AND mt".$i.".meta_value", $wpdb->posts . ".post_excerpt", $where);
        $i++;
    }

    return $where;
}

add_filter('posts_where','post_content_to_meta_queries',10,2);

Sunt sigur că poate fi îmbunătățit! Sper să vă fie de folos!

30 iul. 2021 22:43:56
Comentarii

Actualizare: Am folosit această soluție în ultimul an și jumătate. Un adevărat salvator pentru căutările complexe, alături de ACF.

Jeff Oliva Jeff Oliva
19 dec. 2022 15:04:36