All Low add-ons are now owned by EEHarbor. Read the blog post.

Support archive

Low Search Based on EE Native Relationship

Stoyan Vasilev 13 May 2014 20:24 question, complete

Hey,

We have the following task at hand:

We would like to use Low Search to do an advanced search of an Events channel. Some of the fields in this channel are Low Events fields.

All of the entries in the Events channel are associated with another channel called Venues via a native EE relationship field. The entries in the Venues channel have fields populated with latitude, longitude, city (and everything else that the Google Maps API returns) data.

All of our events are in the San Francisco Bay Area and we would like for our Events search on the front-end to be able to filter by city *based on* the geo fields part of the Venues channel. Our intention is to:

A) Keep the data clean, by not moving any of the geo data directly into the Events channel entries if possible.

B) Give the user an HTML form multiselect element (which is part of the Low Search form) populated with the cities which we would allow them to select .

So the question is:

1) Is it possible to do this kind of search (without moving the geo data into the Events channel)?

2) If Yes, do we have to transform the city field (part of the Venues channel) into a category to accomplish this?

Thank you,

St

Replies

  1. Low 14 May 2014 07:28

    Hi Stoyan,

    The Relationships filter parameters in Low Search expect entry IDs as values, just like the category="" parameter takes category IDs. So, you must find a way to list the cities/venues associated with the Venue IDs.

    If your Venue channel has separate fields for the geo data, this shouldn't be a problem; using the Query module, it's possible to output all unique cities with the venue entry IDs grouped together.

    Even neater, you could create a custom extension for Low Search that will take a city name and look up the correct Venues for that city, and set the Relationships filter parameter internally.

    I'd like to point you to my Implementation Aid service, which you might be interested in.

  2. Stoyan Vasilev 14 May 2014 14:35

    Thank you, Low.

    Let me make sure that I understand what you are saying:

    You are suggesting that if we can find a way to query the Venues channel and return the IDs of the Venues (which correspond to a given city), Low Search can add the IDs list as a filter (which gets added to the other Low Search parameters)?

    I have a *really* senior SQL person working on the project and another person with a lot of PHP MVC experience. Getting the job done should not be a problem.

    The question that I have is:

    Where in the Search process do we inject the query which returns the IDs of the Venues (which will be used as a Low Search filter)? Are you suggesting that we do that on the front-end and put them in as a hidden parameter in the Search form OR that we intercept the search within CodeIgniter and add the Venue IDs list as a filter on the back-end?

    The implementation aid services sounds interesting. Once I understand what you are suggesting as an approach I will evaluate internally (with my team) how we would like to proceed. I would be happy to work directly with you if we can afford the service.

    Thanks,
    St

  3. Low 15 May 2014 07:50

    The way I see it, there are 2 options:

    1. Use the Query module to generate the multi-select for the Relationships filter.

    You would need to compose a query using GROUP_CONCAT to generate a pipe-separated list of entry IDs per unique city from the Venues channel. So the query will give you a list of 2 fields: 'entry_ids' and 'city'. You can then output the list like so:

    <select name="child:my_venue_field[]" multiple> 
    {exp:query sql="SELECT..."}
    <option value="{entry_ids}">{city}</option>
    {/exp:query}
    </select>


    This should limit the search to events that have the selected cities as their venue. The downside to this approach is that, depending on how many venues there are, the URL might get very lengthy or even the GROUP_CONCAT clause can truncate the list of IDs (but there’d have to be a lot of venues for that to happen). Also, there’s no way to keep the selection active after form submission like this.

    2. Use an extension to read a city value and set the Relationships filter internally.

    Instead of generating a list of pipe-separated entry IDs, you’d just generate a list of unique cities. You can then name the select-element something custom, like just 'city', eg:

    <select name="city[]" multiple> 
    {exp:query sql="SELECT..."}
    <option value="{city}"{if city IN ({low_search_city}) selected{/if}>{city}</option>
    {/exp:query}
    </select>


    Now you’ve got a parameter 'city' which will do nothing in itself, unless you create an extension using the 'low_search_pre_search' hook. There, you can read the 'city' parameter, get its value, query the DB to get all entry IDs that match that city, and set the Relationships filter with those ids (as a pipe-separated list). Low Search will then see that the Relationships filter is set and will filter the content accordingly.

    This is slightly more work, but the URLs stay cleaner, the search log will make more sense, and you can keep the selection active (as per the conditional in the above code example).

  4. Stoyan Vasilev 15 May 2014 14:43

    Hi,

    Thank you very much for the detailed response. We are after option 2 as we need the selected City (or Cities) to stay active (when the results are returned).

    I understand the idea of populating the city filter and using an extension to query the DB to get the IDs of all venues that match this city. I need a slight clarification on how to execute this:

    You are suggesting that the list of cities is populated before the user has completed their first search. Are you suggesting that the work that the extension does (fetching the IDs of venues matching a given city) is:

    1) done when the page first loads (before the user has hit Submit on the form) and the relationship filter is set directly in the search form via an html select element.
    OR
    2) after the user hits Submit (and the list of venue IDs is set as a relationship filter in the Low Search CodeIgniter code)
    ?

    If you mean #2, could you point me in the direction of the method/data array which allows us to set a relationship filter within the Low Search code.

    Thanks!

    St

  5. Low 15 May 2014 15:14

    I'm assuming there's a single search form that handles everything. In the form, there's the multi-select of cities. Those options are generated when the form is displayed, using the Query module.

    All the extension does is look up entry IDs for any given city/cities and set a parameter accordingly.

    So, that'll be #2.

    Check out Low Search Tag (https://github.com/low/low_search_tag) which is the Tag filter before that became native. It uses the same approach, with the exception that it sets the entry_id parameter. You would need to set the child:my_venue_field parameter.