MongoDB is a general-purpose document database: records are BSON documents grouped into collections, queried with a JSON-like filter language, and indexed with B-tree secondary indexes. The commands on this page come from a RAG project in which each web page is stored as one document holding its URL, title, cleaned text, and embedding vector, so the examples double as a practical reference for inspecting a document store that backs semantic search.
Every production deployment is at least a replica set: one primary takes writes and records them in the oplog, and secondaries replay the oplog to stay in sync. If the primary fails, the members elect a new one automatically. Write concern (w: "majority") controls how many members must acknowledge a write, and read preference controls whether reads may go to secondaries. Sharding partitions a collection across replica sets by a shard key, with the mongos router sending each query to the shards that can hold matching documents.
The collection mixes two kinds of data that are queried differently. Scalar fields such as url and title are filtered with ordinary queries and indexes. The embedding array is only useful to a vector search: either an external index such as FAISS keyed by _id, or MongoDB Atlas Vector Search, which builds an approximate nearest-neighbour index over the field. Storing both together keeps the text and its vector consistent when a page is re-ingested.
# Log in to the MongoDB shell locally
mongosh
# Default port on localhost rag_database:
mongosh mongodb://localhost:27017/rag_database
# View All Documents
db.documents.find().pretty()
# View a Document by ID
db.documents.find({ _id: ObjectId("671f110807e141d70ebe59d8") }).pretty()
# Filter Documents by a Field
db.documents.find({ url: "https://kevinluzbetak.com/1-ai/Gunning-Fog-Index.html" }).pretty()
# Limit the Number of Documents
db.documents.find().limit(5).pretty()
# Skip Documents and Limit
db.documents.find().skip(5).limit(5).pretty()
# Sort Documents
db.documents.find().sort({ title: 1 }).pretty()
# Project Specific Fields
db.documents.find({}, { url: 1, title: 1, content: 1, _id: 0 }).pretty()
# Exclude a Specific Field
db.documents.find({}, { embedding: 0 }).pretty()
# Find Random Document
db.documents.aggregate([{ $sample: { size: 1 } }]).pretty()
# Count the Number of Documents
db.documents.countDocuments()
# Find Documents Matching a Range
db.documents.find({ "score": { $gte: 50, $lte: 100 } }).pretty()
# Find Documents Using Regular Expressions
db.documents.find({ "title": { $regex: "Index", $options: "i" } }).pretty()
# Use $in Operator to Match Multiple Values
db.documents.find({ "title": { $in: ["Gunning-Fog-Index.html", "TF-IDF.html"] } }).pretty()
# Find Documents Based on Field Existence
db.documents.find({ "author": { $exists: true } }).pretty()
# Retrieve and Sort Documents with Pagination
db.documents.find().sort({ _id: 1 }).skip(10).limit(10).pretty()
MongoDB is not a traditional key-value store, but it can function similarly in some contexts. MongoDB is a document-based NoSQL database, where each document (typically represented in BSON format, a binary form of JSON) can have multiple key-value pairs. The keys in a MongoDB document are the field names, and the values are the corresponding data.
url, Value: 'https://kevinluzbetak.com/ai/Gunning-Fog-Index.html'title, Value: 'Gunning-Fog-Index.html'content, Value: 'gunning fog index account ...'embedding, Value: [-0.01926298439502716, 0.03058304823935032, ...]
Each document in MongoDB also has an implicit key-value pair for the _id field:
_id, Value: ObjectId('671f110807e141d70ebe59d8')
The _id field is the primary key in each MongoDB document. It uniquely identifies the document within a collection,
much like how a key works in a key-value database.
In the document you retrieved, the "keys" are the field names (_id, url,
title, content, and embedding), and their "values" are the corresponding
data (e.g., the URL, title, content text, and embedding vector).
Without an index, every filter in the reference above scans the whole collection. Create indexes for the fields you filter and sort on, and use explain() to confirm the plan uses them (look for IXSCAN rather than COLLSCAN):
// Unique index so re-ingesting a page cannot create duplicates
db.documents.createIndex({ url: 1 }, { unique: true })
// Text index for keyword search over content
db.documents.createIndex({ content: "text", title: "text" })
db.documents.find({ $text: { $search: "gunning fog" } }, { score: { $meta: "textScore" }, embedding: 0 })
.sort({ score: { $meta: "textScore" } })
// Check the plan
db.documents.find({ url: "https://kevinluzbetak.com/" }).explain("executionStats")
// Aggregation: documents per site section, largest first
db.documents.aggregate([
{ $project: { section: { $arrayElemAt: [ { $split: ["$url", "/"] }, 3 ] } } },
{ $group: { _id: "$section", pages: { $sum: 1 } } },
{ $sort: { pages: -1 } }
])
from pymongo import MongoClient, UpdateOne
client = MongoClient("mongodb://localhost:27017")
docs = client["rag_database"]["documents"]
pages = [
{"url": "https://kevinluzbetak.com/a.html", "title": "a.html", "content": "alpha text", "embedding": [0.1, 0.2]},
{"url": "https://kevinluzbetak.com/b.html", "title": "b.html", "content": "beta text", "embedding": [0.3, 0.1]},
]
# Upsert by url: insert new pages, replace changed ones, never duplicate
ops = [UpdateOne({"url": p["url"]}, {"$set": p}, upsert=True) for p in pages]
result = docs.bulk_write(ops)
print(result.upserted_count, result.modified_count)
for d in docs.find({"title": {"$regex": "^a"}}, {"embedding": 0}).limit(5):
print(d["_id"], d["url"])
Upserting on a unique url makes ingestion idempotent: running the loader twice leaves one document per page.
| Situation | MongoDB | Alternative |
|---|---|---|
| Varied, nested records read as a unit | Good fit | PostgreSQL JSONB if you also need joins |
| Heavy multi-table joins and reporting | Possible () but awkward | Relational database or warehouse |
| Offline-first device sync | Not the core design | CouchDB |
| Very high write rates, simple key access | Workable with sharding | Cassandra |
| Vector search beside documents | Atlas Vector Search or external index | pgvector, dedicated vector DB |
explain().skip(n) still walks n documents; paginate by the last seen _id instead.w: "majority" for important data.