Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Geo search

Do Geo searching in Optimizely Graph.

Geo search lets Optimizely Graph match and rank content against geographic coordinates, so applications can deliver location-aware experiences such as nearby-store lookups, regional concert venues, sports event listings, and travel content. Tag content with latitude (lat) and longitude (lon) so the query can return the closest, most relevant items for each visitor.

Location data improves personalization by making content more relevant to users, which can improve conversion rates and engagement. Optimizely Graph supports storing, querying, and ranking such content by fully using the geographic coordinate system.

Prerequisites

Before running geo search queries, define a GeoPoint field on the affected content type and confirm the API key used for the query has read access to the content. Without a GeoPoint field in the schema, the geo operators have nothing to match against.

GeoPoint type

The GeoPoint type is the custom field type that enables every geo search query in this article. Configure it on any content type that needs location-based filtering, sorting, or faceting.

Fields can be configured with a custom type. To enable geo search, use a custom type called GeoPoint that consists of two properties, lat and lon, which are of type float.

"contentTypes":{
  "test": {
    "contentType": [],
    "properties": {
      "GeoPointField": {
        "type": "GeoPoint"
      }
    }
  }
}

The following is an example of this type implemented as a field, where valid coordinates are -90 to 90 for lat (latitude) and -180 to 180 for lon (longitude):

"GeoPointField": {
  "lat": 59.334591,
  "lon": 18.06324
}

//With useTypedFieldNames = true
"GeoPointField$$GeoPoint": {
  "lat": 59.334591,
  "lon": 18.06324
}

//With useTypedFieldNames = true and searchable
"GeoPointField$$GeoPoint___searchable": {
  "lat": 59.334591,
  "lon": 18.06324
}

Search

Geo search exposes three operators that handle distance filters, polygon filters, and existence checks, so callers can combine the operators that match the experience they are building.

📘

Geo search with full-text search

The GeoPoint type is not supported for full-text search with _fulltext. If a field with this type is set as searchable, Optimizely Graph does not add it to _fulltext.

Fields configured as GeoPoint have the following special operators for geo search:

  • distance – Filters results by distance using the following parameters:

    ParameterDescriptionDefault
    originThe latitude and longitude of the reference point.Mandatory
    radiusThe maximum distance from the origin.1000
    unitThe distance unit. Accepted values are M (meters), KM (kilometers), CM (centimeters), MM (millimeters), MI (miles), IN (inches), and YD (yards).M
  • withIn – Retrieves content within a polygon shape described by a set of geo coordinates. It requires at least four coordinates, and the polygon must be closed, so the starting and end coordinates must be the same. To filter on multiple polygons, use the _or Boolean operator.

  • exist – Checks whether the field exists in your content. The previous operators automatically ignore the field or treat it as undefined if it does not exist.

Examples

The following examples show the distance and withIn operators in queries the calling layer can adapt for production use.

The following example retrieves biography pages of people within 1,200 km from London:

{
  BiographyPage(
    where: {
      GeoPointField: { 
        distance: { 
          radius: 1200, 
          origin: { lat: 51.509865, lon: -0.118092 }, 
          unit: KM 
        } 
      }
    }
  ) {
    total
    items {
      Name
      GeoPointField {
        lat
        lon
      }
    }
  }
}

The following example searches within a polygon with a set of coordinates in Stockholm using withIn. The polygon shape is not complete in this example because of space considerations:

{
  BiographyPage(
    where: {
      GeoPointField: {
        withIn: [
          { lat: 59.381319, lon: 17.839936 }
          { lat: 59.381092, lon: 17.830846 }
          { lat: 59.381125, lon: 17.83038 }
          { lat: 59.381354, lon: 17.828188 }
          { lat: 59.381639, lon: 17.825344 }
          { lat: 59.385607, lon: 17.846594 }
          { lat: 59.384736, lon: 17.845159 }
          { lat: 59.383968, lon: 17.843804 }
          { lat: 59.383115, lon: 17.842609 }
          { lat: 59.381319, lon: 17.839936 }
        ]
      }
    }
  ) {
    total
    items {
      Name
      GeoPointField {
        lat
        lon
      }
    }
  }
}

Sort

Sorting orders results by distance from a reference point, which lets the calling layer present a nearest-first list without writing client-side ranking logic.

Rank by closest (default) locations near an origin using orderBy, which defaults to order: ASC. The order does not need to be set when sorting nearest locations.

Optionally, and not commonly used, specify farthest distance by setting order: DESC. If null values or missing fields exist, they are treated as infinity and sorted to the top.

Example

{
  BiographyPage(
    orderBy: { GeoPointField: { origin: { lat: 52.377956, lon: 4.897070 } } }
  ) {
    total
    items {
      Name
      GeoPointField {
        lat
        lon
      }
    }
  }
}

Facet

Faceting groups content items by distance range so the application can render distance buckets (such as "within 5 miles" or "5-10 miles") that drive a refinable search experience.

Create groups of content items by defining them with ranges (at least one object with from and to) with a unit (default M, meters) from an origin (mandatory). The unit supports the same metrics as defined for the distance operator. These groups can then be used to filter by the distance operator.

📘

Note

If distance is not specified, no facets are returned.

Example

{
  BiographyPage (limit: 0) {
    facets {
      GeoPointField(
        distance: {
          ranges: [{ to: 500 }, { from: 500, to: 1000 }, { from: 1000 }]
          unit: MI
          origin: { lat: 59.334591, lon: 18.06324 }
        }
      ) {
        name
        count
      }
    }
  }
}