3

Elasticsearch version: 7.6.2

I have the following simplified structure and query below.

PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "description": {
        "type": "text"
      },
      "variants": {
        "type": "nested",
        "include_in_parent": true,
        "properties": {
          "price": {
            "type": "double"
          },
          "tags": {
            "type": "text"
          }
        }
      }
    }
  }
}

PUT /products/_doc/1?refresh
{
    "name": "Product Pizza",
    "description": "Product Pizza Description",
    "variants": [
        { "price": 100, "tags": ["capri", "small", "noketchup"] },
        { "price": 110, "tags": ["capri", "medium", "ketchup"] },
        { "price": 300, "tags": ["capri", "medium", "noketchup"] },
        { "price": 210, "tags": ["vege", "medium", "ketchup"] },
        { "price": 220, "tags": ["vege", "medium", "noketchup"] },
        { "price": 330, "tags": ["vege", "large", "ketchup"] }
    ]
}


PUT /products/_doc/2?refresh
{
  "name": "Product Towel",
  "description": "Product Towel Description",
  "variants": [
    { "price": 50, "tags": ["blue", "small"] },
    { "price": 60, "tags": ["blue","medium"] },
    { "price": 70, "tags": ["blue","large"] },
    { "price": 55, "tags": ["red","small"] },
    { "price": 65, "tags": ["red","medium"] },
    { "price": 75, "tags": ["red","large"] }
  ]
}


GET /products/_search
{
  "track_scores": true,
  "query": {
    "nested": {
      "path": "variants",
      "inner_hits": {
        "size": 10
      },
      "query": {
        "multi_match": {
          "query": "vege medium",
          "operator": "or",
          "fields": [
            "variants.tags"
          ]
        }
      }
    }
  },
  "sort": [
    {
      "variants.price": {
        "mode": "min",
        "nested": {
          "filter": {
            "multi_match": {
              "query": "vege medium",
              "operator": "or",
              "fields": [
                "variants.tags"
              ]
            }
          },
          "path": "variants"
        },
        "order": "asc"
      }
    }
  ]
}

What I need to achieve is somehow get the best matching nested result and then take the price field from that nested variant.

  1. When sorting by min price, the sort should return 210 for first product and 60 for the second product
  • Match both tags "vege" "medium"
  1. When sorting by max price, the sort should return 220 for first product and 65 for the second product
  • Match one tag "medium"

I tried couple of things

  1. Using "and" instead of "or" for the multi_match but then the second product is excluded from the results.
  2. Using max_children for the sort nested but it takes only the first nested from the array (after filtered, it doesn't sort them by score).
  3. I checked if it's possible to sort the nested variants by score before executing max_children, apparently it's not.

Any suggestion is appreciated, this is not the final structure so any ideas for changing the structure are also welcomed.

How is something like this achieved, maybe using scripts ?

Val
  • 207,596
  • 13
  • 358
  • 360
  • When sorting by min price, the sort would return 110 for the first product because it also matches `medium` – Val Jun 12 '21 at 03:35

0 Answers0