user2512324
user2512324

Reputation: 791

Retrieve only one object inside an array elasticsearch

I have an index named books which has reviews as an object which can handle arrays. While retrieving data, in a particular case I only want the review having maximum rating.

"books" :{ 
    "reviews": {
        "properties": {
            "rating": {
                "type": "float"
             },
            "comments": {
                "type": "string"
             }
         }
     },
    "author" : {
        "type" : "string"
    }
 }

Many books can have many reviews each having some rating. For a particular use case I only want the result set to have the reviews having maximum rating. I need to build a search query for that kind of result.

POST books/_search
{
    "size": 51,

    "sort": [
   {
      "reviews.rating": {
         "order": "asc",
         "mode" : "min"
      }
   }
],
"fields": [
   "reviews","author"]
}

By using script_fields one can build dynamic fields but not objects. Else I could have made a dynamic object reviews having one field as rating and another as comment.

Upvotes: 1

Views: 186

Answers (1)

imotov
imotov

Reputation: 30163

script_fields can be used to build both dynamic fields and objects:

curl -XDELETE localhost:9200/test-idx
curl -XPUT localhost:9200/test-idx -d '{
    "mappings": {
        "books" :{ 
            "reviews": {
                "properties": {
                    "rating": {
                        "type": "float"
                     },
                    "comments": {
                        "type": "string"
                     }
                 }
             },
            "author" : {
                "type" : "string"
            }
        }
    }
}'

curl -XPOST "localhost:9200/test-idx/books?refresh=true" -d '{
    "reviews": [{
        "rating": 5.5,
        "comments": "So-so"
    }, {
        "rating": 9.8,
        "comments": "Awesome"
    }, {
        "rating": 1.2,
        "comments": "Awful"
    }],
    "author": "Roversial, Cont"
}'

curl "localhost:9200/test-idx/books/_search?pretty" -d '{
    "fields": ["author"],
    "script_fields": {
        "highest_review": {
            "script": "max_rating = 0.0; max_review = null; for(review : _source[\"reviews\"]) {  if (review.rating > max_rating) { max_review = review; max_rating = review.rating;}} max_review"
        }
    }
}'

Upvotes: 2

Related Questions