How to compare value exactly from array of document with params in script plainess?

Hi everyone, I have a index example above:

PUT target_index
{
  "mappings": {
    "properties": {
      "targetoperator": { "type": "keyword" },
      "targetvalue": { 
        "type": "float"
      }
    }
  }
}
PUT target_index/_doc/1
{
  "targetoperator": [">", "=="],
  "targetvalue": [4, 5]
}

PUT target_index/_doc/2
{
  "targetoperator": ["<", "<="],
  "targetvalue": [6, 5.5]
}

PUT target_index/_doc/3
{
  "targetoperator": [">=", ">", "<", "<="],
  "targetvalue": [2, 4, 8, 8.5]
}

PUT target_index/_doc/4
{
  "targetoperator": [">"],
  "targetvalue": [2.5]
}

PUT target_index/_doc/5
{
  "targetoperator": ["!="],
  "targetvalue": [3.5]
}

I run a script query above:

GET target_index/_search
{
  "query": {
    "script": {
      "script": { 
        "source": """
          double userCriteria = params.userTarget.seniority;
          def targetoperator = doc['targetoperator'];
          def targetvalue = doc['targetvalue'];
          if (targetoperator.size() == targetvalue.size()) {
            for (int i = 0; i < targetoperator.size(); i++) {
              def operaVal = targetoperator[i];
              def valueVal = targetvalue[i];
              if (operaVal == "<=") {
                if (valueVal <= userCriteria) {
                  return true;
                }
              }
            }
          }
          return false;
        """, 
        "params": {
          "userTarget": {
            "gender": "male",
            "seniority": 6
          }
        }
      }
    }
  },
  "_source": [
    "targetoperator",
    "targetvalue"
  ]
}

My target want check value of field params.userTarget.seniority <=
value of field targetvalue ?

But, search result return about document id = 2, and id = 3.

{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "target_index",
        "_id": "2",
        "_score": 1,
        "_source": {
          "targetoperator": [
            "<",
            "<="
          ],
          "targetvalue": [
            6,
            5.5
          ]
        }
      },
      {
        "_index": "target_index",
        "_id": "3",
        "_score": 1,
        "_source": {
          "targetoperator": [
            ">=",
            ">",
            "<",
            "<="
          ],
          "targetvalue": [
            2,
            4,
            8,
            8.5
          ]
        }
      }
    ]
  }
}

If correct, the result return only document id = 3. :pensive:

Hi @duyhunter1001

From what I understand, you use the item's position in the array to validate if the value is lower than the useCriteria, which is 6. I don't understand why you expect to get the doc id 3, whereas in the operator "<=" position, the targetvalue will be 8.5

I could be wrong but I saw somewhere that using the array, elasticsearch does not guarantee the order in which it was indexed when you retrieve the field. I could be wrong, let's see what the members say.

1 Like

Hi @RabBit_BR , I have confusion in my test case. The above case is correct.
The following case is not correct:

PUT target_index/_doc/1
{
  "targetoperator": ["<", "<="],
  "targetvalue": [6, 5.5]
}

PUT target_index/_doc/2
{
  "targetoperator": [">=", ">", "<", "<="],
  "targetvalue": [2, 4, 8, 8.5]
}

GET target_index/_search
{
  "query": {
    "script": {
      "script": { 
        "lang": "painless",
        "source": """
          double userCriteria = params.userTarget.seniority;
          def targetoperator = doc['targetoperator'];
          def targetvalue = doc['targetvalue'];
          if (targetoperator.size() == targetvalue.size()) {
            for (int i = 0; i < targetoperator.size(); i++) {
              def operaVal = targetoperator[i];
              def valueVal = targetvalue[i];
              if (operaVal == "<=") {
                if (!(userCriteria <= valueVal)) {
                  return false;
                }
              }
              if (operaVal == ">") {
                if (!(userCriteria > valueVal)) {
                  return false;
                }
              }
            }
          }
          return true;
        """, 
        "params": {
          "userTarget": {
            "gender": "male",
            "seniority": 7
          }
        }
      }
    }
  }
}

It return empty document, if correct, It will return about document id = 2 because userCriteria <= 8.5

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.