Queries, Inserts, Updates and Deletes

Translation table

The most fundamental commands for reading and writing unfortunately have a slightly different names in different contexts. It's the same gang of four all the time though:

Context Query Insert Update Delete
CRUD names Read Create Update Delete
SQL equivalent SELECT INSERT UPDATE DELETE
mongod server-side commands find insert update delete
mongo shell find()
findOne()
insert()
insertOne()
insertMany()
update()
updateOne()
updateMany()
remove()
deleteOne()
deleteMany()
pymongo driver find()
find_one()
insert_one
insert_many
update_one()
update_many()
delete_one()
delete_many()
mongoc driver mongoc_collection_find ..._insert ..._update ..._delete
Java driver find() insertOne()
insertMany()
updateOne()
updateMany()
deleteOne()
deleteMany()
(Mostly) extinct aliases query() upsert*
save
Legacy Wire
Protocol msgs
OP_QUERY OP_INSERT OP_UPDATE OP_DELETE

Variations such as insertOne(), updateMany() are just syntactic sugar.

E.g. 1. There is no such thing as an 'insertOne' command etc. in a wire protocol message. The driver will construct a { insert: <collection_name>, documents: [ ... ] } BSON command object that has only one document in the "documents" array.

E.g. 2. An updateMany(<query>, u: <update>) function call will become a { update: <collection_name>, updates: [ q: <query_spec>, u: <update_spec>, multi: true ] } command.

E.g. 3. An upsert is also really an update command like just above, but with a upsert: true flag present and set to true.

Historical detour

The documentation for the delete command says "New in version 2.6". 'What! Was MongoDB an append-only database before then?'

Actually the same version info is written for the other two write commands (insert, update). And the find command has "New in version 3.2"!

What this points out is that before v2.6 did not accept BSON command objects that were formatted like {"insert": <collection_name>, ...}, {"update": <collection_name>, ...}, {"delete": <collection_name>, ...}. Instead the clients sent an OP_INSERT, OP_UDPATE or OP_DELETE mongo wire protocol message. The target collection name was up a level in a field in the wire protocol message object, whilst every other field was still in the same format in the BSON object packed within.

The difference may seem merely lexical, but the introducing a BSON format spec to allow an array of writes in each wire request (rather than just one) improved the way that bulk writes could be done.

{"find": <collection_name>, ...} likewise wasn't recognized by the server until v3.2. Before then queries were always sent in an OP_QUERY wire protocol message. The OP_QUERY wire protocol is still used a lot as a legacy workaround that won't be resolved until OP_MSG becomes standard. Until then a query might be a classic OP_QUERY with the target collection in the wire protocol field, or it might be an OP_QUERY with the fake "$cmd" name string in the wire protocol field for collection, and the packed BSON object will have "find": <collection_name> as it first key-value pair (indicating that is the command name and what its scope is).

FYI in v3.2 an OP_COMMAND message type was introduced in tandem with the packing of queries in a more generic command BSON object, but it never became mainstream. It was considered deprecated by v3.6 and is removed completely by v4.2.