Adding a custom field filter in a Relevanssi search takes a little bit of programming, because the filter needs to create a meta_query that Relevanssi understands.
Let’s assume we have some colour information in a custom field that’s called colour_field
, and we want to use that to filter the search results. First, let’s add a dropdown in our search form:
<select name="colour"> <option value="any">Any colour</option> <option value="red">Red</option> <option value="green">Green</option> </select>
Then, we need to tell WordPress that we want to use a query variable called colour
(the name here needs to match the name
attribute of the select
in the form):
add_filter( 'query_vars', 'rlv_add_qv' ); function rlv_add_qv( $qv ) { $qv[] = 'colour'; return $qv; }
Then we need a function that reads in the query variable, formulates a meta_query and passes that to Relevanssi:
add_filter( 'relevanssi_modify_wp_query', 'rlv_add_meta_query' ); function rlv_add_meta_query( $query ) { if ( isset( $query->query_vars['colour'] ) && ! empty( $query->query_vars['colour'] ) ) { $meta_query = array( array( 'key' => 'colour_field', 'value' => $query->query_vars['colour'], 'compare' => '=', ), ); $query->set( 'meta_query', $meta_query ); } return $query; }
If you need to have multiple meta fields in the same search, you must add them to the same meta_query – you can only have one. WP_Query documentation has a good example of what that looks like, so take a look at that if you need multiple custom fields.
The changes is on Relevanssi or on other plugin? For example, on my plugin.
These sample codes go to your theme. No need to edit any plugins.
Is necessary buy the premium version to do that? I try to use that code with no success with the free version. Thank you.
No, this will work with the free version as well.
Sorry, i think the example explains how to search by a dropdown box without using the input field. A missunderstanding.
hi. i have i metadata named chkbox2 and there is a value again. i want to add this values to searching… but i cant add. how can i add ?
Relevanssi settings, “Custom fields to index”, add “chkbox2” to the list and rebuild the index.
i’m trying now. i looked my database. this plugin creating cache. very nice. but i want to ask a question again. is it recreate again cache after new posts…?
If you mean the index then yes, Relevanssi indexes automatically when you add new posts.
very nice. i liked that. i’m trying but i cant activate custom post meta field. post_meta chkbox2 not indexing and again i want to fix it. because your addon is perfect.
Have you set Relevanssi to index custom fields? Have you rebuilt the index afterwards?
http://prntscr.com/edn7ji my setting is here. is there any problem. i rebuild it.
i saw now i set up false..
i will try again. and back…
That’s the “Extra user field” option, for user fields. User fields are for user profiles, not for post meta. The “Custom fields to index” option is empty, you should have the custom field name there.
rebuilding now. slow because db is big.and worked fine now. i’m realy idiot 🙂 because i’m trying for 3 hours 🙂
thanks a lots.
i recreate and not worked. 🙁 this chkbox2 is post_meta. is this problem ?
Is there a way to filter custom field results based on _GET parameters? Here’s what I’m trying to achieve:
mysite.com/?s=keyword&mycustomfield=customvalue
This should return posts that match the search keyword AND that have the custom field “mycustomfield” set to the value “customvalue”.
Sure, just use the example above, but instead of looking at $query->query_vars, fetch the parameters from the $_GET array.
I have something very similar to this running however it appears that the second (custom field) is only displaying results if a term in the search box also gives a result.
I.E.
If I have “/?s=&mycustomfield=customvalue” nothing will display.
But if I have “/?s=keyword&mycustomfield=” I get appropriate results.
I also get appropriate results with “/?s=keyword&mycustomfield=customvalue”
Can you explain why this would be. My code matches what you have above + the swapout of $query->query_vars to $_GET
Katrina, Relevanssi requires a search term to work. In order to get results without a search term, see this knowledge base page.
Hi,
I followed this steps but still the search results doesn’t match anything. Plus, the search template used is actually the “content.php” one. How can I tell the system to show results with a particular template?
See WordPress template hierarchy. WordPress will use search.php, if it exists.
Is the search using Relevanssi? Is the relevanssi_modify_wp_query filter being triggered? (If you add a var_dump($query); exit(); in the function before return $query;, what do you see?
where should I place those functions?
Theme functions.php.
Love your Search plugin!!!
So If I had 3x search filters for example:
Any colour
Red
Green
Any age
infant
Child
Any Gender
Boy
Gril
Then in functions.php
Would the add_filters be separate?
add_filter(‘query_vars’, ‘rlv_add_qv’);
function rlv_add_qv($qv) {
$qv[] = ‘colour’;
return $qv;
}
add_filter(‘query_vars’, ‘rlv_add_qv’);
function rlv_add_qv($qv) {
$qv[] = ‘gender’;
return $qv;
}
add_filter(‘query_vars’, ‘rlv_add_qv’);
function rlv_add_qv($qv) {
$qv[] = ‘age’;
return $qv;
}
Would the function be separate or all in one (bit unsure on this bit if (isset($query->query_vars[‘colour’])) {
if (!empty($query->query_vars[‘colour’])) { ? as it has the [colour] part.)
add_filter(‘relevanssi_modify_wp_query’, ‘rlv_add_meta_query’);
function rlv_add_meta_query($query) {
if (isset($query->query_vars[‘colour’])) {
if (!empty($query->query_vars[‘colour’])) {
$meta_query = array(
array(
‘key’ => ‘colour_field’,
‘value’ => $query->query_vars[‘colour’],
‘compare’ => ‘=’,
),
array(
‘key’ => ‘gender_field’,
‘value’ => $query->query_vars[‘gender’],
‘compare’ => ‘=’,
),
array(
‘key’ => ‘age_field’,
‘value’ => $query->query_vars[‘age’],
‘compare’ => ‘=’,
),
);
$query->set(‘meta_query’, $meta_query);
}
}
return $query;
}
Making three meta query filters gets complicated. You have to add only those that are in the query, but no others. Create a meta_query array, then check for each query variable and if it exists in the $query->query_vars, add it to the meta_query, then add the meta_query only once to the $query.
where should I place these functions?
Theme functions.php.
Hello.
Thanks for the plugin.
I have an “apart_room” field. I specify it in ‘key’, right? (‘key’ => ‘apart_room’,)
If I select 3 in the search, in the address bar http://2u/?Color=3 and the search does not work (all posts are displayed).
If I’m changing to http://2u/?S=3, then everything works and a post is displayed with which the “apart_room” field = 3
I just started learning php. I do not understand something. Could you explain.
Thank.
Alex, no, that’s not how it works. Read up on meta_query.
I paste the code into the theme function file. What do you do after this?
If you have added all the pieces, you should now have a
select
field in your search form that works and restricts the search results based on a custom field. That is – everything should just work, without any further action required.Is it somehow possible to use this filter, to prevent Relevanssi from splitting a word containing commas? I’m trying to make it possible to search on a custom field, which holds a word containing commas. But when searching on this word, Relevanssi splits the word, which then returns too many irrelevent results.
It works with hyphens and dashes, when “Hyphens and dashes” is set to “Keep” in “Advanced Settings” but I need to make it work with commas as well. Any suggestions?
– Thanks
Jesper, see “Keeping decimal separators” in these instructions. You don’t want to keep all commas, because that will lead to a big mess, so you need some special steps to only keep commas within words.
So, instead of keeping periods followed by digits (
/\.(\d)/
), you want to keep commas followed by any word characters (/,(\w)/
). That should do the trick.Amazing! It works!
Thank you very much 🙂
I’m adding a meta query for two filters. Previously I was only searching based off of text in the post title. Will I need to include these two custom fields in the index, and then rebuild the index? I’m asking because this worked, but the query went from 200ms to 3 seconds. Would adding the custom fields to the index and re-indexing bring the time down?
Eric, it depends on what you’re actually doing. As you noticed, meta queries can be very slow. Adding the custom fields in the index doesn’t help the meta queries, because the your meta queries likely don’t have anything to do with Relevanssi index. What are you actually doing with the meta queries? Perhaps there’s a way to achieve the same without the slow queries.
We have a search field that searches based on text in the title of the post. There are also two dropdown filters that filter based off of two other criteria.
Adding this filter definitely slowed down the query.
Looking for the fastest way to search text but also filter by a few other fields.
Eric, meta queries are the slowest kind of filter, so it’s often fastest to not use them. You can instead have Relevanssi search for everything and then use a filter function on
relevanssi_hits_filter
to weed out the unwanted posts. It’s often faster that way.Hello,
I’ve got a custom field that give the status of the custom post type. Is it possible to exclude from the search results custom posts with a certain status?
Thanks a lot
Christophe, yes. I’d do that in indexing: create a filter on
relevanssi_do_not_index
hook that checks the status from the custom field and returnstrue
if the post should not be indexed and passes the current value otherwise.OK. Thanks a lot Mikko.
Do I define this filter in function.php ? And like this ?
add_filter( ‘relevanssi_do_not_index’, ‘rlv_only_validstatus’ );
function rlv_only_validstatus( $block, $post_id ) {
$status = get_post_meta($post_id,’status’, true);
$invalidstatus = array(4,5,9);
if ( ! empty( $status ) && in_array($status,$invalidstatus) {
$block = true;
}
else{
$block = false;
}
return $block;
}
Christophe, that’s correct. Note that you’re missing a parentheses there:
if ( ! empty( $status ) && in_array($status,$invalidstatus) {
should be
if ( ! empty( $status ) && in_array($status,$invalidstatus) ) {
Indeed… Thank you Mikko 🙂
Hi,
So I’ve got two custom fields and want to search through some custom posts by these two fields. Your code works great (thanks!) but I’m struggling to figure out what the relations should be like for the search to work the way it should and I’m not finding anything in the docs that make this more clear.
So if a person searches for a member (custom post type), they can select the Membership Category and Forum the member belongs to under two dropdowns.
It works fine matching members to the correct Membership Category and Forum, but the problem comes when you search for Member A, under Membership Category 1 and Forum b for example.
Then Member A displays in the search results, but that member only belongs to Membership Category 1 and Forum a, not Forum b. I only want Member A to display if both dropdowns match its custom fields or if one dropdown matches and the other is set to all.
Here is the code I have so far –
add_filter(‘relevanssi_modify_wp_query’, ‘rlv_add_meta_query’);
function rlv_add_meta_query($query) {
if (isset($query->query_vars[‘m-category’]) || isset($query->query_vars[‘forum’])) {
if (!empty($query->query_vars[‘m-category’]) || !empty($query->query_vars[‘forum’])) {
$meta_query = array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘membership_category’,
‘value’ => $query->query_vars[‘m-category’],
‘compare’ => ‘=’,
),
array(
‘key’ => ‘forum’,
‘value’ => $query->query_vars[‘forum’],
‘compare’ => ‘=’,
),
);
$query->set(‘meta_query’, $meta_query);
}
}
return $query;
}
Hope that makes sense, thanks in advance!
Marcel, you’re expecting an AND search, but setting an OR search. Change the
relation
parameter toAND
to make this an AND search. Then both of the subqueries must match (and only set both subqueries in the cases where there’s a parameter and don’t set it when all results are fine).Hi Mikko, I’ve tried with AND, it’s closer to what I want yes, the only problem is when you search for a post but only use the one dropdown. So e.g. I select a Membership Category but don’t select a Forum and keep the Forum dropdown on ‘All’ or ‘Any’, I still want all the custom posts to display that fall under the selected Membership Category. It doesn’t return any posts since it’s expecting both fields to match.
Not sure if this is possible within the meta query? Is that what you mean with your last sentence “(and only set both subqueries in the cases where there’s a parameter and don’t set it when all results are fine).” To use a different if statement to check the contents of the fields?
Marcel, when nothing is selected in the Forum dropdown, you don’t include the Forum subquery, just use the Membership Category subquery. When you only have a Forum selected, use only the Forum subquery. That takes some if queries, yes, but is not a complicated thing.
Thank you so much! Got it working properly, kept overthinking it.
Have a great day further