Getting Geolocalized Results in a JavaScript Search Page

When at least some of your indexed content includes geospatial (longitude and latitude values), you probably want to take advantage of this data to be able to optimize search results based on a reference location.

Your index contains Automatic Teller Machine (ATM) items with fields for their address, as well as longitude and latitude values. You want to be able to return addresses of the closest ATMs where your customer can go based on their current location.

In the JavaScript Search Framework, you can manage geospatial data using a query function ($qf) that allows generating dynamic field values for the duration of a query. The query function calculates a mathematical value from the search results data and injects it in a temporary field for each result. The dynamic field value can then be used for almost any normal numerical field operation, including further query functions.

In the geospatial data case, you can use the following query function to inject a field (@distance) which contains the dynamically calculated value of the as the crow flies distance (in meters) between a current position and the location in each item. In the same query, you can add a @distance field expression to return only items for which the as the crow flies distance is within 1000 meters.

$qf(function:'dist(@latitude, @longitude, 37.77919, -122.41914)', fieldName: 'distance') @distance<1000

where:

  • @latitude and @longitude are fields available in your index
  • 37.77919 and -122.41914 are the latitudes and longitude of the current reference position
  • distance is the temporary dynamic field injected in each search result

You can test this query directly in the search box  and then rather include it in the advanced expression of the query with JavaScript for more complex purposes. 

$(function () {
    // Use a means of your choice to get the reference latitude and longitude
    var refLat = "37.77919"; 
    var refLng = "-122.41914";
    var radius = "10000"; // Value in meters
    // Assembling and adding a geolocation query to the advanced expression of the query.
    $("#search").on("buildingQuery", function(e, args){
        var geoQuery = "$qf(function:'dist(@latitude,@longitude," + refLat + "," + refLng + ")', fieldName: 'distance') @distance<" + radius;
        if (args && args.queryBuilder) {
            args.queryBuilder.advancedExpression.add(geoQuery);
            }
        });
    // Initialize the search page
    Coveo.SearchEndpoint.configureOnPremiseEndpoint('/rest/search');
    $('#search').coveo('init');
});

In your index, the fields storing the longitude and latitude values must be floating point numerical fields. For a Coveo Cloud index the field Type must be Decimal (see Managing Fields for a Source). For an on-premises Coveo index, the field Type must be Floating point (see Adding or Modifying Custom Fields).