Elasticsearch 6.8.5.
I'm confused about the use of _doc as a type. It's possible to create an index with one type of _doc but it also seems like _doc has special meaning in some contexts, including in templates.
Can someone explain to me exactly how _doc is treated under different circumstances, or how it should or shouldn't be used?
Below are some examples of using _doc, the results being the source of my confusion.
If I start a new instance of Elasticsearch and load these two templates
$ curl -s "http://localhost:9200/_template/all?pretty"
{
"all" : {
"order" : 0,
"index_patterns" : [
"*"
],
"settings" : { },
"mappings" : {
"_doc" : {
"properties" : {
"geoip" : {
"type" : "ip"
}
}
}
},
"aliases" : { }
}
}
$ curl -s "http://localhost:9200/_template/testtest?pretty"
{
"testtest" : {
"order" : 99,
"index_patterns" : [
"testtest"
],
"settings" : { },
"mappings" : {
"foo" : { }
},
"aliases" : { }
}
}
Then creating a new document in a new index called testtest works.
$ curl -s -X PUT -H 'Content-Type: application/json' "http://localhost:9200/testtest/foo/1?pretty" -d '{ "hello" : "world" }'
{
"_index" : "testtest",
"_type" : "foo",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
But, unless _doc has some special meaning, it shouldn't, because I've got two templates with mappings for two different types that apply to an index called testtest.
The resulting index contains only one document type of foo, but has mappings that are only specified in the template with mappings for type _doc
$ curl -s "http://localhost:9200/testtest/_mapping?pretty"
{
"testtest" : {
"mappings" : {
"foo" : {
"properties" : {
"geoip" : {
"type" : "ip"
},
"hello" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
So it's like _doc was used as a placeholder and mappings for it merged with those for other types.
Additionally curious is that the type of the document I created with the type specified as foo changes depending on how I request it.
$ curl -s "http://localhost:9200/testtest/foo/1?pretty"
{
"_index" : "testtest",
"_type" : "foo",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"hello" : "world"
}
}
$ curl -s "http://localhost:9200/testtest/_doc/1?pretty"
{
"_index" : "testtest",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"hello" : "world"
}
}
If I create a new document in a new index with a name only the all template applies to and specify the type as _doc the index gets created with a document type of _doc.
$ curl -s -X PUT -H 'Content-Type: application/json' "http://localhost:9200/testtest_doc/_doc/1?pretty" -d '{ "hello" : "world" }'
{
"_index" : "testtest_doc",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
$ curl -s "http://localhost:9200/testtest_doc/_mapping?pretty"
{
"testtest_doc" : {
"mappings" : {
"_doc" : {
"properties" : {
"geoip" : {
"type" : "ip"
},
"hello" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
$ curl -s "http://localhost:9200/testtest_doc/_doc/1?pretty"
{
"_index" : "testtest_doc",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"hello" : "world"
}
}
$ curl -s "http://localhost:9200/testtest_doc/foo/1?pretty"
{
"_index" : "testtest_doc",
"_type" : "foo",
"_id" : "1",
"found" : false
}
So in that case it seems _doc in the template wasn't treated like a placeholder, it was treated as a literal string.
If I delete the testtest index then create it again, but this time specifying a document type of _doc.
$ curl -s -X DELETE "http://localhost:9200/testtest/?pretty"
{
"acknowledged" : true
}
$ curl -s -X PUT -H 'Content-Type: application/json' "http://localhost:9200/testtest/_doc/1?pretty" -d '{ "hello" : "world" }'
{
"_index" : "testtest",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
That tells me the index was created with a document type of _doc. Except the only mapping in the index is for type foo
$ curl -s "http://localhost:9200/testtest/_mapping?pretty"
{
"testtest" : {
"mappings" : {
"foo" : {
"properties" : {
"geoip" : {
"type" : "ip"
},
"hello" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
And I can request the document using type foo
$ curl -s "http://localhost:9200/testtest/_doc/1?pretty"
{
"_index" : "testtest",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"hello" : "world"
}
}
So in that case _doc was treated like a placeholder not a literal string.