Limit search results for users by tag (and limit to 5 tags) I've read as many forum posts and documentation but am a little stumped over a specific use-case. Currently the search page grabs the url segment, loops through a verified user group, and uses the .shuffle() function to randomise order. 

I'm looking to limit search results using relations with a customTagsField on a user's profile. It also needs to limit results using only the first 5 tags that the user has entered in customTagField, in the order they are arranged in control panel.



&lt;div class="grid-item 1/1"&gt;
    &lt;h1&gt;Search Results&lt;/h1&gt;

    {% set query   = craft.request.getParam('q') %}
    {% set results = craft.users.group('verified').search(query) %}
    {% set users   = shuffle(results) %}

    {% if users|length %}
        &lt;p&gt;{{ users|length }} results:&lt;/p&gt;

        &lt;div class="grid"&gt;
        {% for user in users %}
            &lt;div class="grid-item 1/1 mb"&gt;
                &lt;div {# class="grid-item xs-1/4 sm-1/6 lg-1/8" #}&gt;
                        &lt;img class="img-circle" src="{{ user.photoUrl }}" alt=""&gt;
                      &lt;/div&gt;
                &lt;h2 {# class="grid-item 1/1" #}&gt;{{ user.fullName }}&lt;/h2&gt;
                &lt;div {# class="grid-item 1/1" #}&gt;{{ user.intro }}&lt;/div&gt;
                        &lt;div {# class="grid-item 1/1" #}&gt;
                            &lt;a class="btn" href="/profile/{{ user.username }}"&gt;View counsellor&lt;/a&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
        {% endfor %}
        &lt;/div&gt;
    {% else %}
        &lt;p&gt;Your search for “{{ query }}” didn’t return any results.&lt;/p&gt;
    {% endif %}
&lt;/div&gt;


I'm still a bit confused about relatedTo as well as source and target terminology, even though I've read quite a bit about it!

Is it as simple as changing results to:

{% set results = craft.users.group('verified').relatedTo(customTagsFieldHandle).search(query) %}


It doesn't seem possible to limit the tags searched using relatedTo (as you can with craft.tags, so I expect I'll have to edit the for loop somehow. I know about Twig's slice function but I'm not sure how to go about limiting by a user's tag entries.

Does anyone have suggestions for the optimal way to achieve this?
There’s no way to tell the relatedTo param to only factor in the first X relations per source element (the first 5 tags per user, in this case).

I can think of two ways you could accomplish this:

Option 1: Use two Specialism fields

Replace your “Specialism” Tags field with two Categories fields – “Primary Specialism” and “Secondary Specialism”. Limit “Primary” to 5 categories, so no one can ever enter more than 5 specialties in there, and they can list any additional specialties  in the “Secondary” field.

Then from your template, you can limit the search query to only factor in the “Primary” field:

{% set results = craft.users({
    group: 'verified',
    relatedTo: {
        targetElement: craft.categories({
            group: 'specialisms',
            search: query
        }),
        field: 'primarySpecialism'
    }
%}


This method will get more complicated if you do start allowing premium members to be found from both fields down the road; you would need to split it up into two separate user queries – first for the premium members, and then again for the normal members.

Option 2: Automatically store the searchable specialisms in a separate, hidden field

Install the excellent Preparse plugin, and create a new Preparse field called “Searchable Specialisms” with the following Twig code:

{% spaceless %}
    {% for tag in user.specialismTags.limit(5) %}
        {{ tag.title }}
    {% endfor %}
{% endspaceless %}


(Disable the “Show Field” setting so this field doesn’t show up on user profile pages. {% spaceless %} is required to remove initial whitespace character from the newly parsed “Searchable Specialisms” field)

Once the field is created, add it to your User field layout (Settings > Users > Fields) - doesn’t matter where.

Finally, update your set results template code to this:

{% set results = craft.users({
    group: 'verified',
    search: 'searchableSpecialisms:"' ~ query ~ '"'
}) %}


This approach will make it much easier to handle the premium member feature down the road, because you’ll just need to factor in whether they are a premium member or not in the Preparse field settings:

{% set limit = user.isInGroup('premium') ? null : 5 %}
{% for tag in user.specialismTags.limit(limit) %}
    {{ tag.title }}
{% endfor %}