han
han

Reputation: 93

How to sort by a provide value and get only matched element in nested array in Elasticsearch7

It's okay to get all the element back. But I feel docs size is too heavy. How to get match element only in nested array.

Details below, I will be grateful for any help you can provide.

my test index below

PUT test

PUT test/_mapping
{
   "properties": {
      "items": {
         "type": "nested",
         "properties": {
            "item": {
               "type": "keyword"
            },
            "price": {
               "type": "integer"
            }
         }
      }
   }
}


PUT test/_doc/1
{
  "items": [
    {"item": "A", "price": 350},
    {"item": "B", "price": 500}
  ]
}

PUT test/_doc/2
{
  "items": [
    {"item": "A", "price": 400},
    {"item": "C", "price": 200}
  ]
}

PUT test/_doc/3
{
  "items": [
    {"item": "B", "price": 600},
    {"item": "C", "price": 150}
  ]
}

I can get docs which exist item: "B" and sorting by price of item: "B"

Here is the query

POST test/_search
{
  "query" : {
    "nested" : {
      "query" : {
        "term" : {
          "items.item": {
            "value" : "B",
            "boost" : 1.0
          }
        }
      },
      "path" : "items",
      "ignore_unmapped" : false,
      "score_mode" : "none",
      "boost" : 1.0
    }
  },
  "sort":[
      {
        "items.price": {
              "order": "desc",
              "nested": {
                  "path": "items",
                  "filter": {
                    "term" : { "items.item": "B" }
                  }
              }
          }
      }
  ]
}

And Results

[
    {
        "items" : [
            {"item" : "B", "price" : 600},
            {"item" : "C", "price" : 150}
        ]
    },
    {
        "items" : [
            {"item" : "A", "price" : 350},
            {"item" : "B", "price" : 500}
        ]
    }
]

How do I get the result with the item: B only like below

[
    {
        "items" : [
            {"item" : "B", "price" : 600}
        ]
    },
    {
        "items" : [
            {"item" : "B", "price" : 500}
        ]
    }
]

Upvotes: 0

Views: 141

Answers (1)

Bhavya
Bhavya

Reputation: 16172

You can use inner_hits along with the nested query, to get only the matching object in the result

{
  "query": {
    "nested": {
      "query": {
        "term": {
          "items.item": {
            "value": "B",
            "boost": 1.0
          }
        }
      },
      "inner_hits": {},                // note this
      "path": "items",
      "ignore_unmapped": false,
      "score_mode": "none",
      "boost": 1.0
    }
  },
  "sort": [
    {
      "items.price": {
        "order": "desc",
        "nested": {
          "path": "items",
          "filter": {
            "term": {
              "items.item": "B"
            }
          }
        }
      }
    }
  ]
}

Search Result:

"hits": [
      {
        "_index": "68902032",
        "_type": "_doc",
        "_id": "3",
        "_score": null,
        "_source": {
          "items": [
            {
              "item": "B",
              "price": 600
            },
            {
              "item": "C",
              "price": 150
            }
          ]
        },
        "sort": [
          600
        ],
        "inner_hits": {
          "items": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 0.9444616,
              "hits": [
                {
                  "_index": "68902032",
                  "_type": "_doc",
                  "_id": "3",
                  "_nested": {
                    "field": "items",
                    "offset": 0
                  },
                  "_score": 0.9444616,
                  "_source": {
                    "item": "B",
                    "price": 600          // note this
                  }
                }
              ]
            }
          }
        }
      },
      {
        "_index": "68902032",
        "_type": "_doc",
        "_id": "1",
        "_score": null,
        "_source": {
          "items": [
            {
              "item": "A",
              "price": 350
            },
            {
              "item": "B",
              "price": 500
            }
          ]
        },
        "sort": [
          500
        ],
        "inner_hits": {
          "items": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 0.9444616,
              "hits": [
                {
                  "_index": "68902032",
                  "_type": "_doc",
                  "_id": "1",
                  "_nested": {
                    "field": "items",
                    "offset": 1
                  },
                  "_score": 0.9444616,
                  "_source": {
                    "item": "B",
                    "price": 500           // note this
                  }
                }
              ]
            }
          }
        }
      }
    ]

Upvotes: 1

Related Questions