Search code examples
elasticsearchelasticsearch-painless

Elasticsearch painless cannot find some fields


Having the documents similar to the following:

{
  "lastModified": "2022-01-14T09:33:48.232Z",
  "uuid": "01234567",
  "started": "2022-01-14T09:31:27.651Z",
  "editing": false,
  "approved": true,
  "statistics": {
    "teams": {
      "team1": {
        "name": "Team1",
        "score": 0,
        "winner": false,
        "apiId": "1"
      },
      "team2": {
        "name": "Team2",
        "score": 2,
        "winner": true,
        "apiId": "2"
      }
    }
  }
}

I try to select only documents where one of the teams has particular apiId. As the statistics.teams is not the list but object (Map in java), I have difficulties to achieve that.

After some tries with regular queries, I ended up with the painless script, but I'm getting the errors anyway.

With this query

{
  "query": {
    "bool": {
      "must": [
        //{"script": { "script": {"source":  "!doc['editing'].value"} }}
        {"script": {
          "script": {
            "inline": "def statistics = doc['statistics'].value; return doc['editing'].value == params.isEditing;",
            "lang": "painless",
            "params":  {
              "isEditing": 2
            }
          }
        }}
      ]
    }
  }
}

Im getting the error bellow. The commented out works fine, painless finds the editing property but not statistics

{
    "error": {
        "root_cause": [
            {
                "type": "script_exception",
                "reason": "runtime error",
                "script_stack": [
                    "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:65)",
                    "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:27)",
                    "statistics = doc['statistics'].value; ",
                    "                 ^---- HERE"
                ],
                "script": "def statistics = doc['statistics'].value; return doc['editing'].value == params.isEditing;",
                "lang": "painless",
                "position": {
                    "offset": 21,
                    "start": 4,
                    "end": 42
                }
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
            {
                "shard": 0,
                "index": "matches2",
                "node": "7K26XVgxRv6Dz8yDMUrhjg",
                "reason": {
                    "type": "script_exception",
                    "reason": "runtime error",
                    "script_stack": [
                        "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:65)",
                        "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:27)",
                        "statistics = doc['statistics'].value; ",
                        "                 ^---- HERE"
                    ],
                    "script": "def statistics = doc['statistics'].value; return doc['editing'].value == params.isEditing;",
                    "lang": "painless",
                    "position": {
                        "offset": 21,
                        "start": 4,
                        "end": 42
                    },
                    "caused_by": {
                        "type": "illegal_argument_exception",
                        "reason": "No field found for [statistics] in mapping"
                    }
                }
            }
        ]
    },
    "status": 400
}

Elasticsearch does not see the statistics parameter of the root document.

Can anyone help me with selecting only documents where one of the teams has the particular apiId?

Thanks a lot!


Solution

  • You don't need any script to achieve that. You can simply use the multi_match query to run the query on multiple fields

    POST test/_search
    {
      "query": {
        "multi_match": {
          "query": "1",
          "fields": ["statistics.teams.*.apiId"]
        }
      }
    }