Autoprediction / Autocomplete Search with Meta Keys

currently I am stuck with my real estate search.

What I am trying to do sounds pretty simple:
I have one field in a search form. I want that field be able to generate auto suggestions / auto complete / auto prediction on input as example:

Person searches for a nice loft in Berlin Charlottenburg, so they pick their options and then input “Char” the input will show options that include that name such as “Charlottenburg” (part) or “Charlottenburg-Wilmersdorf” (district).

I’ve found a few ways to create a prediction in wordpress but mine currently searches all posts of the given custom post type and just highlights the one including the input of the TITLE.

What I want is, that the prediction is looking for the meta value of three meta keys and just show the pridiction of meta values that include the search request.


tl;dr:
Current state:

Input: Char
Prediction TITLE: Clean loft in Berlin, Very charmant home, House in city center

Wanted State:

Input: Char
Prediction META_VALUE: Charlottenburg, Charlottenburg-Wilmersdorf

here is my current code:

functions.php:

<?php
/**
 * Enqueue scripts and styles.
 *
 * @since 1.0.0
 */
function ja_global_enqueues() {
    wp_enqueue_style(
        'jquery-auto-complete',
        'https://cdnjs.cloudflare.com/ajax/libs/jquery-autocomplete/1.0.7/jquery.auto-complete.css',
        array(),
        '1.0.7'
    );
    wp_enqueue_script(
        'jquery-auto-complete',
        'https://cdnjs.cloudflare.com/ajax/libs/jquery-autocomplete/1.0.7/jquery.auto-complete.min.js',
        array( 'jquery' ),
        '1.0.7',
        true
    );
    wp_enqueue_script(
        'global',
        get_template_directory_uri() . '/js/prediction.js',
        array( 'jquery' ),
        '1.0.0',
        true
    );
    wp_localize_script(
        'global',
        'global',
        array(
            'ajax' => admin_url( 'admin-ajax.php' ),
        )
    );
}
add_action( 'wp_enqueue_scripts', 'ja_global_enqueues' );
/**
 * Live autocomplete search feature.
 *
 * @since 1.0.0
 */
function ja_ajax_search() {
    $results = new WP_Query( array(
        'post_type'     => array( 'immomakler_object' ),
        'nopaging'      => true,
        'posts_per_page'=> 100,
    'meta_query'    => array (
      'relation'    => 'AND',
      array(
        'relation' => 'AND',
        array(
          'key'         => 'verkaufstatus',
          'value'       => 'VERKAUFT',
          'compare' => '!='
        )
      )
    )
    ) );
    $items = array();
    if ( !empty( $results->posts ) ) {
        foreach ( $results->posts as $result ) {
            $items[] = $result->post_title;
        }
    }
    wp_send_json_success( $items );
}
add_action( 'wp_ajax_search_site',        'ja_ajax_search' );
add_action( 'wp_ajax_nopriv_search_site', 'ja_ajax_search' );

?>

.js

jQuery(function($){
    var searchRequest;
    $('.prediction').autoComplete({
        minChars: 3,
        source: function(term, suggest){
            try { searchRequest.abort(); } catch(e){}
            searchRequest = $.post(global.ajax, { search: term, action: 'search_site' }, function(res) {
                suggest(res.data);
            });
        }
    });
});

My custom post type is: immomakler_object
My custom meta_keys that I want the values to be searched are: PLZ, ort, regionaler_zusatz

1 Answer
1

If you want to show custom field values, you can’t use WP_Query that select posts.
It seems to me that the only available way is to write a sql query and execute it in $wpdb.

global $wpdb;

if ( isset($_POST['search']) == false || empty($_POST['search']) ) 
   wp_send_json_success( $array() ); 
$s = $_POST['search'];

$meta_keys = ['PLZ', 'ort', 'regionaler_zusatz'];
$limit = 100;
$sql = "SELECT meta_value FROM $wpdb->postmeta pm "
      . " WHERE pm.meta_key IN ('PLZ', 'ort', 'regionaler_zusatz') "
      . "    AND pm.meta_value LIKE %s LIMIT 0, %d ";
$args = ['%'.$s.'%', $limit];
$sql = $wpdb->prepare($sql, $args);
$res = $wpdb->get_results($sql, ARRAY_A);

$data = [];
if ( is_array($res) && !empty($res) ) {
   foreach( $res as $row )
       $data[] = $row['meta_value'];
   // -- or --
   //$data = array_reduce($res, function($carry, $item) {
   //    $carry[] = $item['meta_value'];
   //    return $carry;
   //}, []);
}
wp_send_json_success( $data );

If you don’t store in custom fields (PLZ, ort, regionaler_zusatz) single value, you may need to select matching item from the array.

Leave a Comment