Searching using meta_query in wordpress - php

I'm using wordpress to search some content with a few restrictions. Every time I save a post, I save in meta a related posts array.
Then I'm trying to search all posts which has a certain post as related, I have the following query. Selected post is an id to the post I'm looking for.
I checked $selected_post and it has values like the following one.
$selected_post = "25";
I added the meta value using the following instruction, I'm using update_post_meta. $related_posts contains an array of post ids, like the example below.
update_post_meta( $post->ID, 'related_post', $related_posts );
Query
$arg = array(
'post_type' => 'post',
'posts_per_page' => 5,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'related_post',
'value' => array( $selected_post ),
'compare' => 'IN',
'type' => 'STRING'
),
),
);
I checked this meta in some of my current posts, and I have something like this.
'related_post' => array( '15', '25', '46' );
When I execute this query using WP_Query it always returns me an empty array. I think I need something more in the query to make this works.
Any help would be appreciated.

The problem is that you are trying to query related_posts as if it was an array, but it actually gets serialised when its added to the database.
Using WP_Query on serialized arrays
If you were to add an array of post meta as follows:
$fruit_array = array( 'apple', 'orange', 'banana' );
update_post_meta( $post->ID, 'fruit', $fruit_array );
...the value for fruit in the database would be:
a:3:{i:0;s:5:"apple";i:1;s:6:"orange";i:2;s:6:"banana";}
Therefore you need to use LIKE to search the serialised string for the value you are looking for.
For the above example, your $args would be something like:
$args = array(
'post_type' => 'post',
'posts_per_page' => 5,
'meta_query' => array(
array(
'key' => 'fruit',
'value' => 'apple',
'compare' => 'LIKE',
),
)
);
Search for numbers/post ids
In your case, this is complicated by the fact that you are using post ids. Post ids or numbers aren't an issue specifically, but the problem is that LIKE will also return partial matches, so a query for 14 would also return 141, 1455 etc.
Based on the structure of the serialised string, I believe the following should work:
$args = array(
'post_type' => 'post',
'posts_per_page' => 5,
'meta_query' => array(
array(
'key' => 'related_post',
'value' => '"25"', /* include the double quotes in the search value */
'compare' => 'LIKE',
),
)
);
As the values in the serialised string becomes "25"; including the double quotes in the value you want to search for should work.

Related

WP Query argument to search by post title

I am trying to filter my posts by post title. I can use the code below perfectly to filter by anything in postmeta, but i want to get results that match against the post title. How do i change this so it searches wp_posts as opposed to wp_postmeta? I want to search purely by title of the post.
'meta_query' => array(
array(
'key' => 'post_title',
'value' => $keywords,
'compare' => 'LIKE'
)
)
Not best solution but it works!
$args = array(
'posts_per_page' => 5,
's' => $keywords,
);

How can I use REGEX in a meta query.

I have a string submitted from a form field to my query, for example:
1159
The meta value is CFN-1159 but I want to be able to run the query without always using the full meta value.
My array is as follows:
//The submitted reference code
$ref = $_POST['ref'];
//The array added to the meta query
$ref_query = array(
'meta_key' => 'reference_code',
'meta_value' => array($ref),
'meta_compare' => 'LIKE'
);
Im looking to only return the post with the unique ref code (meta_value).
How could I use REGEX instead of LIKE here to find posts where the meta value "ends with" the submitted string.
Simply use something like that
$query_adresses = array (
'order' => 'ASC',
'post_type'=> 'your_post_type',
'posts_per_page' => '-1',
'meta_query' => array(
array(
'key' => 'reference_code',
'value' => array($_POST['ref']),
'compare' => 'REGEXP'
)
)
);

get_terms - get total number of results when 'include' array is given

I want to get 12 term objects by calling get_terms; and I have a specific array of terms_ids which should come first.
Here is my query so far:
$term_args = array(
'taxonomy' => 'coupon_store',
'number' => 12,
'include' => $location_terms,
'meta_query' => array(
array(
'key' => '_wpc_is_featured',
'value' => 'on',
'compare' => '=',
),
)
);
$store_terms = get_terms( $term_args );
The problem is that since $location_terms consists of only 3 values, the whole result count is also restricted to 3. I know this is not quite possible as per get_terms documentation.
Is there any hack to get the rest 9 results, after getting the 3 from that array?
UPDATE
I have achieved it by using 2 queries as described in #Yoda's answer. Is there any way to get it done by using get_terms only once.
So... this basically doesn't work.
The include parameter sets up a where condition in the SQL query that requires all results to be within the include array.
So, that's not great for what you're after.
However, I do have a solution for you!
$term_args = array(
'taxonomy' => 'coupon_store',
'number' => 12,
'include' => $location_terms,
'meta_query' => array(
array(
'key' => '_wpc_is_featured',
'value' => 'on',
'compare' => '=',
),
)
);
$store_terms_location = get_terms( $term_args );
$term_args = array(
'taxonomy' => 'coupon_store',
'number' => 12 - count($store_terms_location), // only get as many as you still need
'exclude' => $location_terms,
'meta_query' => array(
array(
'key' => '_wpc_is_featured',
'value' => 'on',
'compare' => '=',
),
)
);
$store_terms_other = get_terms( $term_args );
// merge the two arrays together in order of priority
$store_terms = array_merge($store_terms_location, $store_terms_other);
So, to cover what this does:
Get up to 12 location terms
Get the remaining number of terms from a list that excludes the ones we checked for earlier
Merge the two lists together
This should give you the results you need. You can tidy it up, use some conditionals to determine whether the latter part needs to run, etc. Build on the general idea and make it fit what you're trying to do with your code.
What you are trying to do doesn't make a whole lot of sense.
If you already know the identity of the three terms you to have get first in your array, making a query to get those is kinda irrelevant. You could simply make two separate queries and merge the results.
E.g.:
$first_terms = array(
'taxonomy' => 'coupon_store',
'include' => $location_terms,
);
$store_terms_1 = get_terms( $term_args );
$remaining_terms = array(
'taxonomy' => 'coupon_store',
'number' => 9,
'exclude' => $location_terms,
'meta_query' => array(
array(
'key' => '_wpc_is_featured',
'value' => 'on',
'compare' => '=',
),
)
);
$store_terms_2 = get_terms( $term_args );
$resulting_terms = array_merge( $store_terms_1, $store_terms_2 );
Without knowing more about your data, it is not easy to do much more.
Guesstimating a bit, since you are already using term metas in your query, you could add another term meta with the order, and use that to order your results. This way you wouldn't need to hardcode those first three terms that you want to have on top, and you would only need to make one query.
E.g.:
$store_terms = [
'taxonomy' => 'coupon_store',
'number' => 12,
'meta_key' => 'coupon_store_term_order,
'orderby' => 'meta_value_num',
'meta_query' => [
[
'key' => '_wpc_is_featured',
'value' => 'on',
'compare' => '=',
],
]
];
This way, you have to set up a new term meta for your terms (coupon_store_term_order), and save there your desired order. You would need a bit more fiddling (e.g. deal with terms with no defined order, etc).
And logically, I'm further assuming that these three terms are also featured terms. Otherwise, making two requests and merging is still the only logical way to go.

WP_Query with Custom Field Parameter (checkbox)

I'm trying to set up a custom query that returns only posts that do not have a custom meta field checkbox is checked. The checkbox meta field id is position-filled.
Here is the code I have:
$args = array (
'post_type' => 'jobs',
'posts_per_page' => 4,
'post__not_in' => array(get_the_id()),
'meta_query' => array(
array(
'key' => 'position-filled',
'value' => 'on', // also tried passing null and removing 'compare'
'compare' => '!=' // also tried 'NOT LIKE'
)
),
);
$customQuery = new WP_Query($args);
However, this returns no posts (I have made certain there are posts without the checkbox checked.
Any idea what I'm doing wrong?
I've run into similar issues when adding custom fields to existing posts/pages where I needed to search on "unchecked" or "unselected" fields.
It boils down to the fact that the query is actually saying, "Give me posts where the meta key (position-filled) is populated, but not populated with a value of 'on'".
Does it work if you re-save your post with the checkbox being unchecked?
If so, you might also try using the 'compare' value of 'NOT EXISTS'. Although I believe if you use NOT EXISTS and then someone saves an older post without the checkbox being checked, it will exist (with a blank value).
[edit]
I forgot to mention that you can build a query with either situation being true (the NOT EXISTS or it does exist but the value is blank/unchecked).
$args = array(
'post_type' => 'jobs',
'posts_per_page' => 4,
'post__not_in' => array(get_the_id()),
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'position-filled',
'value' => 'on',
'compare' => '!='
),
array(
'key' => 'position-filled',
'value' => '',
'compare' => 'NOT EXISTS'
)
)
);
You can chain multiple comparisons together and using the relation property of OR, either one should return true.

wordpress meta query key serialized array

So im having some problems getting this query working, im using a meta query to get values that have been stored as a serialized array. Im using the "LIKE" operator like so:
query_posts(array(
'post_type' => 'product',
's' => $keyword,
'meta_query' => array(
array(
'key' => 'raw_data',
'value' => '"'.$collection.'"',
'compare' => 'LIKE'
),
),
$taxQuery => array(
array(
'taxonomy' => 'product_category',
'field' => 'slug',
'terms' => array( $brandOne, $brandTwo, $brandThree )
)),
'posts_per_page' => '24',
'paged' => $paged,
'post_status'=>'publish' ,
'order'=>'ASC',
));
}
But What I need is target a specific key instead of getting the entire table of "raw_data" I need to get something like $raw_data["COLLECT"] and then query the value.
Anything you guys can think of would be great!
your question about how one can query on serialized data has already been discussed in this post, you may find answer there : https://wordpress.stackexchange.com/questions/16709/meta-query-with-meta-values-as-serialize-arrays

Categories