If you've been using our Delivery API for a while now, you've probably carried out some sort of search to build rich interactions with your content.

Our search is built on top of Elasticsearch – a fast, reliable, and scalable search platform. For some time now we've been meaning to make some improvements to the way we handle search, but this process hasn't been without its challenges.

Building a product for both on-premise installations as well as our cloud platform isn't an easy task, and as we outlined at Velocity last year, our focus is now on cloud – with 11.3 being our last on-premise release.

This decision has enabled us to upgrade Elasticsearch, make adjustments to our cloud platform, handle data migration centrally, scale easily, and given us the ability to continue building on these new search improvements and performance gains.

Improved search query performance

The performance of searches through our Delivery API has been drastically improved. The processing that used to take place after the content has been retrieved from Elasticsearch is now done upfront and stored with the document – shaving valuable time from your performance budget. In some cases we’ve seen an increase of up to 50%.

We previously carried out some extra processing of entries after they were returned from Elasticsearch. This included operations such as resolving link information, checking if linked entries still existed, and mapping in the URIs of images and assets. Each one of these steps in processing would add additional time for a search to be returned.

Auto resolution of images, assets and entries

The content type ID and URIs for images, assets, and entries are now automatically resolved and included in a Delivery API response. You no longer need to use the linkDepth property to obtain this additional information. This makes it especially helpful when you want to display a link or an image on a page without making extra requests.

Previously if you wanted to know the type or URI of a linked asset, image or entry you would have to specify a linkDepth of 1.

Behind the scenes this would make additional requests to get data which was then mapped in to the entry. The downside of this approach was that all the fields for the entry were returned for each link, which would in turn increase the payload.

In the case of an image or asset this was almost always the case, as you generally want the URI property to display an image or provide a link to a file.

With the latest changes the linkDepth property is no longer necessary if you just need the URI or type – making these searches much faster.

Examples

Entry link in 11.3

{
    "entry": {
        "sys": {
            "id": "015e3e82-8451-42ee-99eb-155445c5b2f8",
            "dataFormat": "entry"
        }
    }
}

Entry link in 12

{
    "entry": {
      "sys": {
        "dataFormat": "entry",
        "contentTypeId": "movie",
        "id": "015e3e82-8451-42ee-99eb-155445c5b2f8",
        "uri": "/movies/deadpool"
      }
    }
}

Image link in 11.3

{
    "image": {
        "asset": {
            "sys": {
                "id": "9eceb739-7b8b-4e63-a332-23ccf3489a00",
                "dataFormat": "asset"
            },
            "caption": "Hold onto your chimichangas, folks. From the studio that brought you all 3 Taken films comes the block-busting, fourth-wall-breaking masterpiece about Marvel Comics’ sexiest anti-hero!",
            "altText": "Deadpool Marvel character jumping over a car",
            "transformations": "crop=644,503,316,192"
        }
    }
}

Image link in 12

{
    "image": {
        "altText": "Deadpool Marvel character jumping over a car",
        "transformations": "crop=644,503,316,192",
        "caption": "Hold onto your chimichangas, folks. From the studio that brought you all 3 Taken films comes the block-busting, fourth-wall-breaking masterpiece about Marvel Comics’ sexiest anti-hero!",
        "asset": {
            "sys": {
                "dataFormat": "asset",
                "contentTypeId": "image",
                "id": "bd9690c8-6198-476a-b108-6fbbb71b4c27",
                "uri": "/image-library/deadpool.x6c66a57c.jpg?crop=644,503,316,192"
            }
        }
    }
}

Geo-distance ordering

Prior to this release, when you used the distanceWithin search operator to search for a location within a given distance there was no way to order the results by distance.

Now, when you carry out a distance within search using the Delivery API, we return the distance for each location from the specified geo point. The distance is based on the unit of measurement in the query. This enables you to easily order the results.

Example

Take a search for locations within 150 miles of London returned in ascending order:

{
    "where": [
        {
            "field": "sys.contentTypeId",
            "equalTo": "locationDistanceSearch"
        },
        {
            "field": "sys.versionStatus",
            "equalTo": "latest"
        },
        {
            "field": "location",
            "distanceWithin": {
                "lat": "51.5074",
                "lon": "0.1278",
                "distance": "150mi"
            }
        }
    ],
    "orderBy": [
        {
            "asc": "location"
        }
    ],
    "fields": [
        "entryTitle",
        "location"
    ]
}

This now returns you the following results:

{
    "pageIndex": 0,
    "pageSize": 25,
    "totalCount": 3,
    "pageCount": 1,
    "items": [
        {
            "location": {
                "lat": 50.822530000000008,
                "lon": -0.13716299999998682,
                "distance": 48.69
            },
            "sys": {
                "dataFormat": "entry",
                "contentTypeId": "locationDistanceSearch",
                "language": "en-GB",
                "id": "d7e16a1f-cbfe-41a0-a6c3-c7bffdffff88",
                "uri": null
            },
            "entryTitle": "Brighton"
        },
        {
            "location": {
                "lat": 51.7520209,
                "lon": -1.2577263000000585,
                "distance": 61.78
            },
            "sys": {
                "dataFormat": "entry",
                "contentTypeId": "locationDistanceSearch",
                "language": "en-GB",
                "id": "d166e3ef-56da-429d-9f06-fdd6715ffded",
                "uri": null
            },
            "entryTitle": "Oxford"
        },
        {
            "location": {
                "lat": 52.367749,
                "lon": -2.7139128999999684,
                "distance": 134.84
            },
            "sys": {
                "dataFormat": "entry",
                "contentTypeId": "locationDistanceSearch",
                "language": "en-GB",
                "id": "26730949-6679-43c2-a4dc-03700d45abd2",
                "uri": null
            },
            "entryTitle": "Ludlow"
        }
    ]

As you can see, each of the location fields has an additional distance property. This represents the distance from the position provided in the search query. The unit of measurement matches the unit you specified in the query.

Cloud architecture

These changes were only possible by making Contensis 12 a cloud-only release. This move sets a foundation of quicker releases in the future. If you're not already on our cloud platform, or you're interested in finding out more, please send us a message and we'll be in touch.

Subscribe to our stories 

Richard Saunders

About the Author

Richard is the product owner for Contensis – our CMS. He sets the direction and roadmap for the product. His background includes both user experience and front-end design.

Follow Richard

More stories from Zengenti