Using Elasticsearch pinned queries to promote specific results

blog-thumbnail-generic-release.png

In this article, learn how pinned queries in Elasticsearch can work for you through practical use cases.

What is a pinned query and how can I use it?

Pinned queries were first released in Elasticsearch 7.4 and are used to promote a chosen document, or documents, above any other documents that are at the top of the results for a certain query. It can be used for document promotion or guided searches where some documents must appear in the top results even when the relevancy score is low.

Here are a few practical use cases for pinned queries:

  • You are developing a knowledge center and monitoring user clicks on each article. The most frequently clicked articles for a given query should be displayed at the top of the page.
  • You want to show the newly launched product on top of the search as promotion. Additionally, for some of the products, you wish to use this feature for seasonal marketing.

Pinned query implementation

Let’s start by using a sample product data set to develop our pinned query.

Sample data indexing

PUT product/_bulk
{ "index" : { "_id": "prod101" } }
{ "brand" : "Apple", "model" : "iphone 11", "price": 800 }
{ "index" : { "_id": "prod102" } }
{ "brand" : "Samsung", "model" : "galaxy m32", "price": 700 }
{ "index" : { "_id": "prod103"} }
{ "brand" : "Apple", "model" : "iphone 13", "price": 1000 }
{ "index" : { "_id": "prod104"} }
{ "brand" : "Apple", "model" : "iphone 12", "price": 900 }
{ "index" : { "_id": "prod104"} }
{ "brand" : "Apple", "model" : "iphone 7", "price": 400 }

Simple search without pinned query

POST product/_search
{
 "query": {
   "match": {
     "model": "iphone"
   }
 }
}

Response:

"hits": [
     {
       "_index": "product",
       "_id": "prod101",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 11",
         "price": 800
       }
     },
     {
       "_index": "product",
       "_id": "prod103",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 13",
         "price": 1000
       }
     },
     {
       "_index": "product",
       "_id": "prod104",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 12",
         "price": 900
       }
     },
     {
       "_index": "product",
       "_id": "prod105",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 7",
         "price": 400
       }
     }
   ]

Currently, you can see that products are sorted by relevance and recently launched items do not appear at the top. Now let’s see how we can promote the recently released product on top using pinned query.

Sample pinned query

Here, we’re trying to promote the newest iPhone.

POST product/_search
{
 "query": {
   "pinned": {
     "ids": [ "prod103", "prod104"],
     "organic": {
       "match": {
         "model": "iphone"
       }
     }
   }
 }
}

Response of pinned query:

On top of the results that Elasticsearch returns, you can see an iPhone 13 and an iPhone 12, respectively, with the other results directly below them.

"hits": [
     {
       "_index": "product",
       "_id": "prod103",
       "_score": 1.7014124e+38,
       "_source": {
         "brand": "Apple",
         "model": "iphone 13",
         "price": 1000
       }
     },
     {
       "_index": "product",
       "_id": "prod104",
       "_score": 1.7014122e+38,
       "_source": {
         "brand": "Apple",
         "model": "iphone 12",
         "price": 900
       }
     },
     {
       "_index": "product",
       "_id": "prod101",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 11",
         "price": 800
       }
     },
     {
       "_index": "product",
       "_id": "prod105",
       "_score": 0.2578291,
       "_source": {
         "brand": "Apple",
         "model": "iphone 7",
         "price": 400
       }
     }
   ]

How to use pinned query with multiple indices

If you want to search for a product across many indices, use the query below with the index name.

GET /_search
{
 "query": {
   "pinned": {
     "docs": [
       {
         "_index": "product-01",
         "_id": "prod101"
       },
       {
         "_index": "product-01",
         "_id": "prod102"
       },
       {
         "_index": "product-02",
         "_id": "prod105"
       }
     ],
     "organic": {
       "match": {
         "model": "iphone"
       }
     }
   }
 }
}

Please be aware that you can only supply up to 100 ids for pinned queries.

The pinned query result won’t be available in below case

Elasticsearch returns documents by default based on relevance; however, let’s say that for some queries you need a specific sort option, such as based on date, product amount, etc. You won’t receive a pinned result in this case because the sort doesn’t take relevance into account.

Let’s try to promote the cheaper iPhone 7 and iPhone 11 and use price sorting.

POST product/_search
{
 "sort": [
   {
     "price": {
       "order": "desc"
     }
   }
 ],
 "query": {
   "pinned": {
     "ids": [ "prod105", "prod101"],
     "organic": {
       "match": {
         "model": "iphone"
       }
     }
   }
 }
}

Response:

It should appear at the top since we’re attempting to promote the iPhone 7 and iPhone 11. However, in this instance, the pinned query will not be taken into account because we sorted on price in descending order.

"hits": [
     {
       "_index": "product",
       "_id": "prod103",
       "_score": null,
       "_source": {
         "brand": "Apple",
         "model": "iphone 13",
         "price": 1000
       },
       "sort": [
         1000
       ]
     },
     {
       "_index": "product",
       "_id": "prod104",
       "_score": null,
       "_source": {
         "brand": "Apple",
         "model": "iphone 12",
         "price": 900
       },
       "sort": [
         900
       ]
     },
     {
       "_index": "product",
       "_id": "prod101",
       "_score": null,
       "_source": {
         "brand": "Apple",
         "model": "iphone 11",
         "price": 800
       },
       "sort": [
         800
       ]
     },
     {
       "_index": "product",
       "_id": "prod105",
       "_score": null,
       "_source": {
         "brand": "Apple",
         "model": "iphone 7",
         "price": 400
       },
       "sort": [
         400
       ]
     }
   ]
About the Author

Sagar Patel a member of the Elastic developer community. He is an Elastic Certified Engineer with 6+ years of experience in development of Cognitive Search and Log Monitoring Application. Sagar has hands-on expertise with a variety of search technologies, including Elasticsearch, as well as a track record of creating enterprise search projects to assist content processing, including document classification and relevance optimization. He worked on extracting content from scanned file or images using OCR process and has experience with extracting structured and unstructured content using ML/NLP.