3
votes

Currently, I'm trying to implement a variation of the car example here:

https://www.elastic.co/blog/managing-relations-inside-elasticsearch

If I run:

PUT /vehicle/_doc/1
{  
   "metadata":[  
      {  
         "key":"make",
         "value":"Saturn"
      },
      {  
         "key":"year",
         "value":"2015"
      }
   ]
}

the code works correctly.

But if I delete the index and change 2015 from a string to a number:

DELETE /vehicle
PUT /vehicle/_doc/1
{  
   "metadata":[  
      {  
         "key":"make",
         "value":"Saturn"
      },
      {  
         "key":"year",
         "value":2015
      }
   ]
}

I get the following error message:

{ "error": { "root_cause": [ { "type": "illegal_argument_exception", "reason": "mapper [metadata.value] of different type, current_type [long], merged_type [text]" } ], "type": "illegal_argument_exception", "reason": "mapper [metadata.value] of different type, current_type [long], merged_type [text]" }, "status": 400 }

How do I fix this error?

1

1 Answers

3
votes
PUT /vehicle/_doc/1
{  
   "metadata":[  
      {  
         "key":"make",
         "value":"Saturn"
      },
      {  
         "key":"year",
         "value":2015
      }
   ]
}

After deleting the index and then trying to index a new document as above, the following steps takes place:

  1. When elastic could not find an index by the name of vehicle and auto index creation is enabled (which is by default enabled) it will create a new index named as vehicle.
  2. Based on the input document elastic now tries to make best guess of the datatype for the fields of the document. This is know as dynamic field mapping.
  3. For the above document since metadata is an array of objects the field metadata is assumed to be of object data type.
  4. Now comes the step to decide the data type of fields of individual object. When it encounters the first object it finds two fields key and value. Both these fields have string value (make and Saturn respectively) and hence elastic identifies the datatype for both the fields as text.
  5. Elastic then try to define the mapping as below:

      {
        "properties": {
          "metadata": {
            "properties": {
              "key": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "value": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          }
        }

When it encounter the second object where the value of value field is numeric (2015) which it guesses the datatype as long. This results in conflict with the previously identified datatype which was text. A field can not be of mixed data type. Data types are strict, and hence the error.

To resolve the error you need to make sure the input values for the fields are of same type for each of the object as below:

PUT /vehicle/_doc/1
{  
   "metadata":[  
      {  
         "key":"make",
         "value":2016
      },
      {  
         "key":"year",
         "value":2015
      }
   ]
}

For above it could be better used as:

PUT /vehicle/_doc/1
{  
   "metadata":[  
      {  
         "make":"Saturn",
         "year": 2015
      }
   ]
}