When an _id index is implicitly created through collection creation, it can only include the fields key, name, v, ns, and collation. However, when you use the createIndexes command, it accepts any valid index option except {sparse: true}, {unique: false}, and partialFilterExpression. This leads to unusual specs for the _id index.
> db.createCollection("c") > db.c.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.c" } ] > db.c.drop() > db.createCollection("c", {autoIndexId: false}) > db.c.createIndexes({_id: 1}, {unique: true}) > db.c.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.c", "unique" : true } ]
Worse, it lets you create _id indexes like:
> db.createCollection("c", {autoIndexId: false}) > db.c.createIndexes({_id: 1}, {expireAfterSeconds: 3600}) > db.c.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.c", "expireAfterSeconds" : 3600 } ]
This would lead us to erroneously believe that an old _id index with this option was a TTL index. We should reject all options besides key, name, v, ns, and collation for _id indexes created through createIndexes.
Note: If you try to create an index with key pattern other than {_id: 1} and name "_id_", this succeeds. Instead, we should reject the command.