---
setup:
  - do:
      indices.create:
        index: sensor
        body:
          settings:
            number_of_shards: 1
            number_of_replicas: 0
          mappings:
            runtime:
              day_of_week:
                type: keyword
                script: |
                  emit(doc['timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
              # Test fetching from _source
              day_of_week_from_source:
                type: keyword
                script: |
                  Instant instant = Instant.ofEpochMilli(params._source.timestamp);
                  ZonedDateTime dt = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"));
                  emit(dt.dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
              # Test fetching many values
              day_of_week_letters:
                type: keyword
                script: |
                  for (String dow: doc['day_of_week']) {
                    for (int i = 0; i < dow.length(); i++) {
                      emit(dow.charAt(i).toString());
                    }
                  }
              prefixed_node:
                type: keyword
                script:
                  source: |
                    for (String node : params._fields.node.values) {
                      emit(params.prefix + node);
                    }
                  params:
                    prefix: node_
            properties:
              timestamp:
                type: date
              temperature:
                type: long
              voltage:
                type: double
              node:
                type: keyword
                store: true

  - do:
      bulk:
        index: sensor
        refresh: true
        body: |
          {"index":{}}
          {"timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"}
          {"index":{}}
          {"timestamp": 1516642894000, "temperature": 201, "voltage": 5.8, "node": "b"}
          {"index":{}}
          {"timestamp": 1516556494000, "temperature": 202, "voltage": 5.1, "node": "a"}
          {"index":{}}
          {"timestamp": 1516470094000, "temperature": 198, "voltage": 5.6, "node": "b"}
          {"index":{}}
          {"timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"}
          {"index":{}}
          {"timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"}

---
"get mapping":
  - do:
      indices.get_mapping:
        index: sensor
  - match: {sensor.mappings.runtime.day_of_week.type: keyword }
  - match:
      sensor.mappings.runtime.day_of_week.script.source: |
        emit(doc['timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
  - match: {sensor.mappings.runtime.day_of_week.script.lang: painless }

# --- TODO get field mappings needs to be adapted
# "get field mapping":
#  - do:
#      indices.get_field_mapping:
#        index: sensor
#        fields: day_of_week
#        include_defaults: true
#  - match:
#      sensor.mappings.day_of_week.mapping.day_of_week:
#        type: keyword
#        script:
#          source: |
#            emit(doc['timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
#          lang: painless
#        meta: {}
#
---
"fetch fields":
  - do:
      search:
        index: sensor
        body:
          sort: timestamp
          fields: [day_of_week, day_of_week_from_source, day_of_week_letters, prefixed_node]
  - match: {hits.total.value: 6}
  - match: {hits.hits.0.fields.day_of_week: [Thursday] }
  - match: {hits.hits.0.fields.day_of_week_from_source: [Thursday] }
  - match: {hits.hits.0.fields.day_of_week_letters: [T, a, d, h, r, s, u, y] }
  - match: {hits.hits.0.fields.prefixed_node: [node_c] }

---
"fetch multiple stored fields":
  - requires:
      cluster_features: ["gte_v8.14.0"]
      reason: "bug fixed in 8.14"

  - do:
      indices.create:
        index: sensor-test
        body:
          settings:
            number_of_shards: 1
            number_of_replicas: 0
          mappings:
            runtime:
              prefixed_node:
                type: keyword
                script:
                  source: |
                    for (String node : params._fields.node.values) {
                      emit(params.prefix + node);
                    }
                  params:
                    prefix: node_
              prefixed_region:
                type: keyword
                script:
                  source: |
                    for (String region : params._fields.region.values) {
                      emit(params.prefix + region)
                    }
                  params:
                    prefix: us-
            properties:
              timestamp:
                type: date
              node:
                type: keyword
                store: true
              region:
                type: keyword
                store: true

  - do:
      bulk:
        index: sensor-test
        refresh: true
        body: |
          {"index":{}}
          {"timestamp": 1516729294000, "node": "a", "region": "west-1" }
          {"index":{}}
          {"timestamp": 1516642894000, "node": "b", "region": "west-2" }
          {"index":{}}
          {"timestamp": 1516556494000, "node": "a", "region": "west-1"}
          {"index":{}}
          {"timestamp": 1516470094000, "node": "b", "region": "west-2"}
          {"index":{}}
          {"timestamp": 1516383694000, "node": "c", "region": "west-2"}
          {"index":{}}
          {"timestamp": 1516297294000, "node": "c", "region": "west-2"}
  - do:
      search:
        index: sensor-test
        body:
          sort: timestamp
          fields: [prefixed_node, prefixed_region]
  - match: {hits.total.value: 6}
  - match: {hits.hits.0.fields.prefixed_node: [node_c] }
  - match: {hits.hits.0.fields.prefixed_region: [us-west-2]}

---
"docvalue_fields":
  - do:
      search:
        index: sensor
        body:
          sort: timestamp
          docvalue_fields: [day_of_week, day_of_week_from_source, day_of_week_letters, prefixed_node]
  - match: {hits.total.value: 6}
  - match: {hits.hits.0.fields.day_of_week: [Thursday] }
  - match: {hits.hits.0.fields.day_of_week_from_source: [Thursday] }
  - match: {hits.hits.0.fields.day_of_week_letters: [T, a, d, h, r, s, u, y] }
  - match: {hits.hits.0.fields.prefixed_node: [node_c] }

---
"terms agg":
  - do:
      search:
        index: sensor
        body:
          size: 0
          aggs:
            dow:
              terms:
                field: day_of_week
  - match: {hits.total.value: 6}
  - match: {aggregations.dow.buckets.0.key: Friday}
  - match: {aggregations.dow.buckets.0.doc_count: 1}
  - match: {aggregations.dow.buckets.1.key: Monday}
  - match: {aggregations.dow.buckets.1.doc_count: 1}

  # Update the mapping and make sure the cache doesn't still have the old results
  - do:
      indices.put_mapping:
        index: sensor
        body:
          runtime:
            day_of_week:
              type: keyword
              script: |
                emit(doc['timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.SHORT, Locale.ENGLISH));
  - do:
      search:
        index: sensor
        body:
          size: 0
          aggs:
            dow:
              terms:
                field: day_of_week
  - match: {hits.total.value: 6}
  - match: {aggregations.dow.buckets.0.key: Fri}
  - match: {aggregations.dow.buckets.0.doc_count: 1}
  - match: {aggregations.dow.buckets.1.key: Mon}
  - match: {aggregations.dow.buckets.1.doc_count: 1}

---
"term query":
  - do:
      search:
        index: sensor
        body:
          query:
            term:
              day_of_week: Monday
  - match: {hits.total.value: 1}
  - match: {hits.hits.0._source.voltage: 5.8}

---
"highlight term query":
  - do:
      search:
        index: sensor
        body:
          query:
            term:
              day_of_week: Monday
          highlight:
            fields:
              day_of_week: {}

  - match: { hits.hits.0.highlight.day_of_week : [ "<em>Monday</em>" ] }

---
"explain term query":
  - do:
      search:
        index: sensor
        explain: true
        body:
          query:
            term:
              day_of_week: Monday
  - match: {hits.hits.0._explanation.value: 1.0}
  - match: {hits.hits.0._explanation.description: "day_of_week:Monday"}
  - match: {hits.hits.0._explanation.details.0.value: 1.0}
  - match: {hits.hits.0._explanation.details.0.description: 'boost * runtime_field_score'}
  - match: {hits.hits.0._explanation.details.0.details.0.value: 1.0}
  - match: {hits.hits.0._explanation.details.0.details.0.description: 'boost'}
  - match: {hits.hits.0._explanation.details.0.details.1.value: 1.0}
  - match: {hits.hits.0._explanation.details.0.details.1.description: 'runtime_field_score is always 1'}

---
"explain term query with boost":
  - do:
      search:
        index: sensor
        explain: true
        body:
          query:
            term:
              day_of_week:
                value: Monday
                boost: 7
  - match: {hits.hits.0._explanation.value: 7.0}
  - match: {hits.hits.0._explanation.description: "day_of_week:Monday^7.0"}
  - match: {hits.hits.0._explanation.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.description: 'boost * runtime_field_score'}
  - match: {hits.hits.0._explanation.details.0.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.details.0.description: 'boost'}
  - match: {hits.hits.0._explanation.details.0.details.1.value: 1.0}
  - match: {hits.hits.0._explanation.details.0.details.1.description: 'runtime_field_score is always 1'}

---
"explain term query wrapped in script score":
  - do:
      search:
        index: sensor
        explain: true
        body:
          query:
            script_score:
              script:
                source: _score * 1000
              query:
                term:
                  day_of_week:
                    value: Monday
                    boost: 7
  - match: {hits.hits.0._explanation.value: 7000.0}
  - match: {hits.hits.0._explanation.description: "script score function, computed with script:\"Script{type=inline, lang='painless', idOrCode='_score * 1000', options={}, params={}}\""}
  - match: {hits.hits.0._explanation.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.description: '_score: '}
  - match: {hits.hits.0._explanation.details.0.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.details.0.description: "day_of_week:Monday^7.0"}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.description: 'boost * runtime_field_score'}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.details.0.value: 7.0}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.details.0.description: 'boost'}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.details.1.value: 1.0}
  - match: {hits.hits.0._explanation.details.0.details.0.details.0.details.1.description: 'runtime_field_score is always 1'}


---
"match query":
  - do:
      search:
        index: sensor
        body:
          query:
            match:
              day_of_week: Monday
  - match: {hits.total.value: 1}
  - match: {hits.hits.0._source.voltage: 5.8}

  - do:
      search:
        index: sensor
        body:
          query:
            match:
              day_of_week:
                query: Monday
                analyzer: standard
  - match: {hits.total.value: 0}

---
"dynamic mapping update":
  - do:
      bulk:
        index: sensor
        refresh: true
        body: |
          {"index":{}}
          {"animal": "cow"}
  - do:
      search:
        index: sensor
        body:
          query:
            match:
              animal: cow
  - match: {hits.total.value: 1}
  - match: {hits.hits.0._source.animal: cow}

---
"nested":
  - do:
      indices.create:
        index: test
        body:
          settings:
            number_of_shards: 1
            number_of_replicas: 0
          mappings:
            runtime:
              users.first_script:
                type: keyword
                script: emit(doc['users.first'].value)
              users.last_script:
                type: keyword
                script: emit(doc['users.last'].value)
            properties:
              users:
                type: nested
                properties:
                  first:
                    type: keyword
                  last:
                    type: keyword

  - do:
      bulk:
        index: test
        refresh: true
        body: |
          {"index":{"_id": 1}}
          {"group" : "fans", "users" : [{"first" : "John", "last" : "Smith"}, {"first": "Alice", "last": "White"}]}
          {"index":{"_id": 2}}
          {"group" : "fans", "users" : [{"first" : "Mark", "last" : "Doe"}]}

  - do:
      search:
        index: test
        body:
          query:
            nested:
              path: users
              query:
                bool:
                  must:
                    - match:
                        users.first_script: John
                    - match:
                        users.last_script: Smith
  - match: {hits.total.value: 1}

  - do:
      search:
        index: test
        body:
          query:
            nested:
              path: users
              query:
                bool:
                  must:
                    - match:
                        users.first_script: John
                    - match:
                        users.last_script: White
  - match: {hits.total.value: 0}

  - do:
      search:
        body:
          aggs:
            to-users:
              nested:
                path: users
              aggs:
                users:
                  top_hits:
                    sort: users.last_script
  - match: { hits.total.value: 2 }
  - length: { aggregations.to-users.users.hits.hits: 3 }
  - match: { aggregations.to-users.users.hits.hits.0._id: "2" }
  - match: { aggregations.to-users.users.hits.hits.0._index: test }
  - match: { aggregations.to-users.users.hits.hits.0._nested.field: users }
  - match: { aggregations.to-users.users.hits.hits.0._nested.offset: 0 }
  - match: { aggregations.to-users.users.hits.hits.1._id: "1" }
  - match: { aggregations.to-users.users.hits.hits.1._index: test }
  - match: { aggregations.to-users.users.hits.hits.1._nested.field: users }
  - match: { aggregations.to-users.users.hits.hits.1._nested.offset: 0 }
  - match: { aggregations.to-users.users.hits.hits.2._id: "1" }
  - match: { aggregations.to-users.users.hits.hits.2._index: test }
  - match: { aggregations.to-users.users.hits.hits.2._nested.field: users }
  - match: { aggregations.to-users.users.hits.hits.2._nested.offset: 1 }

---
"fetch defined on search request":
  - do:
      search:
        index: sensor
        body:
          runtime_mappings:
            voltage_rating:
              type: keyword
              script: |
                double v = doc['voltage'].value;
                if (v < 4.8) {
                  emit('low');
                } else if (v > 5.2) {
                  emit('high');
                } else {
                  emit('ok');
                }
          fields: [voltage_rating]
          sort: timestamp
  - match: {hits.total.value: 6}
  - match: {hits.hits.0._source.voltage: 4.0}
  - match: {hits.hits.0.fields.voltage_rating: [low]}

---
"match defined on search request":
  - do:
      search:
        index: sensor
        body:
          runtime_mappings:
            voltage.rating:
              type: keyword
              script: |
                double v = doc['voltage'].value;
                if (v < 4.8) {
                  emit('low');
                } else if (v > 5.2) {
                  emit('high');
                } else {
                  emit('ok');
                }
          query:
            match:
              voltage.rating: ok
          sort: timestamp
  - match: {hits.total.value: 2}
  - match: {hits.hits.0._source.voltage: 5.1}

---
"search glob defined on search request":
  - do:
      search:
        index: sensor
        body:
          runtime_mappings:
            voltage.rating:
              type: keyword
              script: |
                double v = doc['voltage'].value;
                if (v < 4.8) {
                  emit('low');
                } else if (v > 5.2) {
                  emit('high');
                } else {
                  emit('ok');
                }
          query:
            simple_query_string:
              fields: [voltage.*]
              query: ok
          sort: timestamp
  - match: {hits.total.value: 2}
  - match: {hits.hits.0._source.voltage: 5.1}


---
"replace object field on search request":
  - do:
      bulk:
        index: student
        refresh: true
        body: |
          {"index":{}}
          {"name": {"first": "Andrew", "last": "Wiggin"}}
          {"index":{}}
          {"name": {"first": "Julian", "last": "Delphiki", "suffix": "II"}}

  - do:
      search:
        index: student
        body:
          runtime_mappings:
            name.first:
              type: keyword
              script: |
                if ('Wiggin'.equals(doc['name.last.keyword'].value)) {
                  emit('Ender');
                } else if ('Delphiki'.equals(doc['name.last.keyword'].value)) {
                  emit('Bean');
                }
          query:
            match:
              name.first: Bean
  - match: {hits.total.value: 1}
  - match: {hits.hits.0._source.name.first: Julian}
