Stickboy
Stickboy

Reputation: 95

Mapping a Map with Dynamic Keys in ElasticSearch

I'm trying to store this kind of data inside an Elasticsearch index

{
  "id": "5644596f9bf67301645999d9",
  "headline": "Scientists Look Beyond Solar System to Study Planet",
  "renditions": {
    "baseImage": {
      "height": 933,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 1400
    },
    "preview": {
      "height": 500,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 400
    },
    "thumbnail": {
      "height": 150,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 125
    }
  }
}

However the mapping keeps adding unique blocks for all the different children of "renditions".

Ideally, I would define a type of child for "renditions" then assert that all objects under it should be like that.

Is this possible?

I've looked into Dynamic Mappings but I've got a bit confused with it all...

Upvotes: 5

Views: 2371

Answers (1)

Mandeep Singh
Mandeep Singh

Reputation: 8234

You can try this mapping with dynamic templates:

PUT /test

PUT /test/_mapping/test
{
   "properties": {
      "id": {
         "type": "string"
      },
      "headline": {
         "type": "string"
      }
   },
   "dynamic_templates": [
      {
         "renditions_objects": {
            "mapping": {
               "dynamic": "strict",
               "type": "object",
               "properties": {
                  "height": {
                     "type": "integer"
                  },
                  "href": {
                     "type": "string"
                  },
                  "mimetype": {
                     "type": "string"
                  },
                  "width": {
                     "type": "integer"
                  }
               }
            },
           "match_mapping_type": "object",
           "path_match": "renditions.*"            
         }      
      }
   ]
}

The line

"dynamic": "strict",

makes sure that you cannot index any document where extra fields are present. The process fails if you try to index something like this:

POST /test/test
{
  "id": "5644596f9bf67301645999d9",
  "headline": "Scientists Look Beyond Solar System to Study Planet",
  "renditions": {
    "baseImage": {
      "height": 933,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 1400,
      "dummy": 12
    },
    "preview": {
      "height": 500,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 400
    },
    "thumbnail": {
      "height": 150,
      "href": "www.imgur.com/animage",
      "mimetype": "image/jpeg",
      "width": 125
    }
  }
}

Notice the extra dummy key in baseImage. It will fail with error:

{
   "error": "StrictDynamicMappingException[mapping set to strict, dynamic introduction of [dummy] within [renditions.baseImage] is not allowed]",
   "status": 400
}

If you want to make it a little relaxed and allow such documents to be indexed, but don't want the extra fields to be indexed, then set dynamic to false. This will not cause any failure while indexing such documents, also the extra field will be present in the _source field. However, that field will not be indexed and you won't be able to perform any query or filter on that field. Hope this helps

Upvotes: 4

Related Questions