EXECUTED, WITH ASSERTIONS
This program was run during verification and its results asserted. The runner that does it is tools/run_mongo_labs.py.
Straight from labs/course-10-mongodb/08_sort_limit.py, unchanged.
"""Experiment 8 — Sorting, limiting and skipping."""
from fixtures import fresh_db
def sorting():
db = fresh_db()
desc = [d["name"] for d in db.students.find().sort("marks.maths", -1)]
assert desc == ["Meena", "Asha", "Kiran", "Ravi", "Bhanu"], desc
asc = [d["name"] for d in db.students.find().sort("marks.maths", 1)]
assert asc == list(reversed(desc))
multi = [(d["dept"], d["marks"]["maths"])
for d in db.students.find().sort([("dept", 1), ("marks.maths", -1)])]
assert multi == [("DS", 88), ("DS", 71), ("DS", 65),
("Stats", 94), ("Stats", 52)], multi
print(f" sort by maths desc -> {desc}")
print(f" multi-key sort (dept asc, maths desc) groups then orders within")
def limit_and_skip():
db = fresh_db()
top3 = [d["name"] for d in db.students.find().sort("marks.maths", -1).limit(3)]
assert top3 == ["Meena", "Asha", "Kiran"]
page2 = [d["name"] for d in db.students.find().sort("_id", 1).skip(2).limit(2)]
assert page2 == ["Meena", "Kiran"], page2
print(f" top 3 by maths: {top3}; page 2 by _id: {page2}")
def order_is_fixed():
"""sort, then skip, then limit -- whatever order you chain them."""
db = fresh_db()
a = [d["name"] for d in db.students.find().sort("marks.maths", -1).limit(3)]
b = [d["name"] for d in db.students.find().limit(3).sort("marks.maths", -1)]
assert a == b == ["Meena", "Asha", "Kiran"], (a, b)
print(" .limit(3).sort(...) == .sort(...).limit(3) -- the server decides")
print(" it sorts EVERYTHING and then takes three, not the reverse")
def range_pagination_beats_skip():
db = fresh_db()
# skip-based
p1 = list(db.students.find().sort("_id", 1).limit(2))
p2 = list(db.students.find().sort("_id", 1).skip(2).limit(2))
p3 = list(db.students.find().sort("_id", 1).skip(4).limit(2))
# range-based: remember the last _id seen
r1 = list(db.students.find().sort("_id", 1).limit(2))
r2 = list(db.students.find({"_id": {"$gt": r1[-1]["_id"]}})
.sort("_id", 1).limit(2))
r3 = list(db.students.find({"_id": {"$gt": r2[-1]["_id"]}})
.sort("_id", 1).limit(2))
for skip_page, range_page in [(p1, r1), (p2, r2), (p3, r3)]:
assert [d["_id"] for d in skip_page] == [d["_id"] for d in range_page]
print(" range pagination gives IDENTICAL pages, and every page costs the")
print(" same -- skip(100000) would walk and discard 100,000 documents")
def cursor_versus_document():
db = fresh_db()
cursor = db.students.find({"_id": 21})
assert not hasattr(cursor, "get"), "find() gives a CURSOR"
assert list(cursor)[0]["name"] == "Asha"
doc = db.students.find_one({"_id": 21})
assert doc["name"] == "Asha", "findOne gives the DOCUMENT"
print(" find() -> a cursor (iterate it); findOne() -> a document or None")
def main():
print("Experiment 8 -- Sorting, limiting, skipping")
# Step 1: Sort
sorting()
# Step 2: Limit and skip
limit_and_skip()
# Step 3: See sort, skip and limit apply in a fixed order
order_is_fixed()
# Step 4: Paginate by range, not by skip
range_pagination_beats_skip()
# Step 5: Tell a cursor from a document
cursor_versus_document()
if __name__ == "__main__":
main()
One experiment from the Document Oriented Database lab. The rest of them, and the theory behind this one, are on the lab page.