HomeDev guideRecipesAPI Reference
Dev guideUser GuidesLegal TermsNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Geo search

How to do geo searching in Optimizely Graph.

Geo search enables the use of geo-coordinated locations to match and rank content effectively. You can deliver personalized results based on user location by geo-tagging content with a geographic coordinate system, such as latitude (lat) and longitude (lon). This feature not only lets users discover nearby businesses and services but also provides access to location-based content, like travel articles, celebrity concert venues, sports events, and noteworthy occurrences.

Leveraging location data enhances personalization, making content more relevant to users, which can lead to improved conversion rates and increased engagement. Optimizely Graph supports storing, querying, and ranking such content by fully utilizing the geographic coordinate system.

GeoPoint type

Fields can be configured with a custom type. To enable geo search, you need to use a custom type called GeoPoint that consists of two properties: lat and lon, which are of type float. Valid coordinates are -90 to 90 for latitude and -180 to 180 for longitude.

The following is an example of this type implemented as a field:

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

How to search

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

  • distance – Filters your results by distance given:
    • an origin – Mandatory
    • a radius
    • Default –1000
    • a unit
      • Default – M / meters
    • The unit can be the following metrics:
      • M – Meters
      • KM – Kilometers
      • CM – Centimeters
      • MM – Millimeters
      • MI – Miles
      • IN – Inches
      • YD – Yards
  • withIn – Retrieves content that is within a polygon shape described by a set of geo coordinates. It requires at least four coordinates, and the polygon needs to be closed, so the starting and end coordinates need to be the same. When you want to filter on multiple polygons, use the _or Boolean operator.
  • exist – Checks if the field exists in your content. But the above operators will automatically ignore or treat it as undefined in case it does not exist.

Examples

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
      }
    }
  }
}

To search within a polygon with a set of coordinates, we have the following example with Stockholm using withIn, but note that 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
      }
    }
  }
}

How to sort

You can rank by closest (default) locations near an origin using orderBy.

Optionally and not commonly used, you can specify by farthest distance by settting order: DESC.

Example

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

How to facet

Groups of content items can be created 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 be then 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
      }
    }
  }
}