mongosh 403 is the official shell, and it is a Node.js 2,131 REPL: the prompt evaluates real JavaScript with db, show, use and the collection API in scope. The legacy mongo shell was removed in MongoDB 6.0 1,815 , so tutorials calling db.collection.count() or print(tojson(x)) are older than the tool you have.
mongosh "mongodb://127.0.0.1:28017/bookshelf"
> db.books.insertMany([{ title: "Eloquent JavaScript", year: 2024, copies: 3 },
{ title: "Designing Data-Intensive Applications", year: 2017, copies: 1 }])
> db.books.find({ year: { $gte: 2020 } }, { title: 1, _id: 0 })
> db.getMongo().getDBNames(){ acknowledged: true,
insertedIds: { '0': ObjectId('6ab1c043de1a6a607f174eba'),
'1': ObjectId('6ab1c043de1a6a607f174ebb') } }
[ { title: 'Eloquent JavaScript' } ]
[ 'admin', 'bookshelf', 'config', 'local', 'mern' ]use bookshelf switches the db handle, and a database appears in show dbs only once it holds data — use on a nonexistent name is not an error, which is why a typo silently creates an empty database on the first insert. Because the shell is JavaScript, it scripts as well as it prompts:
const total = db.books.countDocuments();
const lent = db.books.aggregate([{ $group: { _id: null, copies: { $sum: "$copies" } } }])
.toArray();
console.log(`${total} titles, ${lent[0].copies} copies`);$ mongosh "mongodb://127.0.0.1:28017/bookshelf" --quiet --file report.js 2 titles, 4 copies
--eval "<expression>" does the same for one-liners, and --quiet suppresses the banner so output is pipeable. That pairing is how seed scripts, health checks and CI steps reach MongoDB without a driver (Seeding a Development Database). Results print through EJSON, MongoDB's extended JSON, which is why _id shows as ObjectId('...').