Search code examples
elasticsearchindexingfilterpreconditions

ElasticSearch : how to filter and change an index with an array field to a boolean field?


I am using ElasticSearch 8.6.

Here below is my index :

1st Example

_source" : {
          "fieldA" : "M",
          "fieldB" : "SHOWER PACK",
          "fieldC" : "false",
          "fieldD" : "01",
          "fieldE" : "true",
          "fieldArrayA" : [ "val1","val2", "val3"]
}

I would like to query my index and get something like

IF fieldArrayA.length > 0 and val1 in fieldArrayA, THEN true ELSE false

So I would like to know it were possible to request my index to get the following result:

_source" : {
          "fieldA" : "M",
          "fieldB" : "SHOWER PACK",
          "fieldC" : "false",
          "fieldD" : "01",
          "fieldE" : "true",
          "fieldArrayA_as_boolean" : true
}

what would be the ElasticSearch query ?

2nd Example:

POST tly-idx_test1/_doc
{
  "fieldA": "M",
  "fieldB": "SHOWER PACK",
  "fieldC": "false",
  "fieldD": "01",
  "fieldE": "true",
  "fieldArrayA": [
    "val1",
    "val2",
    "val3"
  ],
   "fieldArrayB": [
    {"fieldB1":"val1"},
    {"fieldB1":"val2"},
    {"fieldB1":"val3"}
  ]
}

The mapping is the following :

PUT tly-idx_test1
{
  "mappings": {
    "properties": {
      "fieldA": {
        "type": "text"
      },
      "fieldArrayA": {
        "type": "keyword"
      },
     "fieldArrayB": {
      "type": "nested",
      "properties": {
        "fieldB1": {
          "type": "keyword",
          "fields": {
            "text": {
              "type": "text",
              "analyzer": "standard"
              }
            }
          }
        }
     },
      "fieldB": {
        "type": "text"
      },
      "fieldC": {
        "type": "text"
      },
      "fieldD": {
        "type": "text"
      },
      "fieldE": {
        "type": "boolean"
      }
    }
  }
}

How to get the following results with

 IF fieldArrayB.length > 0 and val1 in fieldArrayB, THEN true ELSE false

?

  _source" : {
              "fieldA" : "M",
              "fieldB" : "SHOWER PACK",
              "fieldC" : "false",
              "fieldD" : "01",
              "fieldE" : "true",
              "fieldArrayB_as_boolean" : true
    }

Thanks


Solution

  • You can try this using script fields.

    What you want is only possible via script using Elasticsearch. However scripts are not recommended as they are not performant. The other option is to make a query with Terms Query, but you don't have the field you want the "fieldArrayA_as_boolean".

    Still you can receive the results of the Terms Query and in your application create a logic to add this field in your answer, which would be better thinking in the long term.

    Indexing:

    PUT idx_test
    {
      "mappings": {
        "properties": {
          "fieldA": {
            "type": "text"
          },
          "fieldArrayA": {
            "type": "keyword"
          },
          "fieldB": {
            "type": "text"
          },
          "fieldC": {
            "type": "text"
          },
          "fieldD": {
            "type": "text"
          },
          "fieldE": {
            "type": "boolean"
          }
        }
      }
    }
    
    POST idx_test/_doc
    {
      "fieldA": "M",
      "fieldB": "SHOWER PACK",
      "fieldC": "false",
      "fieldD": "01",
      "fieldE": "true",
      "fieldArrayA": [
        "val1",
        "val2",
        "val3"
      ]
    }
    

    Query:

    {
      "size": 10,
      "_source": "*",
      "script_fields": {
        "fieldArrayA_as_boolean": {
          "script": {
            "source": """
                  def list = doc['fieldArrayA'];
                  return list.size() > 0 && list.contains('val1');
                  """
          }
        }
      },
      "query": {
        "bool": {
          "filter": [
            {
              "script": {
                "script": {
                  "source": """
                  def list = doc['fieldArrayA'];
                  return list.size() > 0 && list.contains('val1');
                  """
                }
              }
            }
          ]
        }
      }
    }
    

    Example with Terms Query

    {
      "size": 10,
      "query": {
        "terms": {
          "fieldArrayA.keyword": [
            "val1"
          ]
        }
      }
    }