W3docs

Сортировка в MongoDB

Узнайте, как сортировать результаты запросов MongoDB в Python с помощью метода sort() PyMongo — по возрастанию, убыванию, нескольким полям.

В этой главе объясняется, как сортировать результаты запросов MongoDB в Python с помощью драйвера pymongo. Вы узнаете, как сортировать по одному полю в порядке возрастания или убывания, сортировать сразу по нескольким полям, комбинировать сортировку с фильтрацией и ограничением, а также понять, когда индекс ускоряет сортировку.

Предварительные требования

Вы должны уметь подключаться к MongoDB и выполнять запросы к документам. Если вы ещё не делали этого, сначала прочитайте MongoDB Find и MongoDB Query.

В примерах ниже предполагается наличие коллекции products в базе данных store. Вставить образцы документов, используемых на этой странице, можно следующим образом:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

# Insert sample data (skip if already inserted)
col.drop()
col.insert_many([
    {"name": "Keyboard", "category": "Electronics", "price": 49.99, "stock": 120},
    {"name": "Mouse",    "category": "Electronics", "price": 29.99, "stock": 85},
    {"name": "Desk",     "category": "Furniture",   "price": 249.99, "stock": 30},
    {"name": "Chair",    "category": "Furniture",   "price": 189.99, "stock": 45},
    {"name": "Monitor",  "category": "Electronics", "price": 319.99, "stock": 60},
    {"name": "Lamp",     "category": "Furniture",   "price": 39.99,  "stock": 200},
])
print("Sample data inserted.")

Метод sort()

Метод sort() вызывается на курсоре (объекте, возвращённом методом find()) и указывает MongoDB, в каком порядке возвращать документы. Его сигнатура:

cursor.sort(key_or_list, direction=None)
  • key_or_list — имя поля (string) при сортировке по одному полю или список кортежей (field, direction) при сортировке по нескольким полям.
  • directionpymongo.ASCENDING (значение 1) или pymongo.DESCENDING (значение -1). Обязателен, когда key_or_list является простой строкой; опускается при использовании формы со списком.

Использование именованных констант (pymongo.ASCENDING / pymongo.DESCENDING) вместо числовых значений делает код более читаемым и помогает избежать ошибок на единицу.

Сортировка по возрастанию

Передайте pymongo.ASCENDING вторым аргументом для сортировки от наименьшего к наибольшему значению:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Ожидаемый вывод (начиная с самых дешёвых):

{'name': 'Mouse', 'price': 29.99}
{'name': 'Lamp', 'price': 39.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Chair', 'price': 189.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Monitor', 'price': 319.99}

Проекция {"_id": 0, "name": 1, "price": 1} ограничивает возвращаемые поля значениями name и price, что делает вывод лаконичным. Проекции рассмотрены в MongoDB Find.

Сортировка по убыванию

Передайте pymongo.DESCENDING, чтобы изменить порядок на обратный (от наибольшего к наименьшему):

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.DESCENDING)

for doc in results:
    print(doc)

Ожидаемый вывод (начиная с самых дорогих):

{'name': 'Monitor', 'price': 319.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Chair', 'price': 189.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Lamp', 'price': 39.99}
{'name': 'Mouse', 'price': 29.99}

Сортировка по нескольким полям

Если нужно сортировать более чем по одному полю — например, сначала по категории, а затем по цене внутри каждой категории — передайте список кортежей (field, direction):

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

results = col.find({}, {"_id": 0, "name": 1, "category": 1, "price": 1}).sort([
    ("category", pymongo.ASCENDING),
    ("price",    pymongo.ASCENDING),
])

for doc in results:
    print(doc)

Ожидаемый вывод (категории от А до Я, внутри каждой категории — от дешёвых к дорогим):

{'name': 'Mouse', 'category': 'Electronics', 'price': 29.99}
{'name': 'Keyboard', 'category': 'Electronics', 'price': 49.99}
{'name': 'Monitor', 'category': 'Electronics', 'price': 319.99}
{'name': 'Lamp', 'category': 'Furniture', 'price': 39.99}
{'name': 'Chair', 'category': 'Furniture', 'price': 189.99}
{'name': 'Desk', 'category': 'Furniture', 'price': 249.99}

Поля сортировки применяются слева направо: MongoDB сначала сортирует все документы по category, а затем разрешает совпадения внутри одного значения категории по price.

Комбинирование sort() с фильтрацией

sort() работает с любым фильтром запроса. Фильтр выбирает подходящие документы, а sort() упорядочивает только их:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

# Find Electronics only, sorted cheapest first
query  = {"category": "Electronics"}
fields = {"_id": 0, "name": 1, "price": 1}

results = col.find(query, fields).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Ожидаемый вывод:

{'name': 'Mouse', 'price': 29.99}
{'name': 'Keyboard', 'price': 49.99}
{'name': 'Monitor', 'price': 319.99}

Дополнительные варианты фильтрации, такие как запросы диапазонов ($gt, $lt) и сопоставление с шаблоном, см. в MongoDB Query.

Комбинирование sort() с limit()

Объедините в цепочку limit() после sort(), чтобы получить первые (или последние) N документов. Порядок цепочки не важен — MongoDB всегда применяет сортировку перед ограничением:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

# Top 3 most expensive products
results = col.find({}, {"_id": 0, "name": 1, "price": 1}) \
             .sort("price", pymongo.DESCENDING) \
             .limit(3)

for doc in results:
    print(doc)

Ожидаемый вывод:

{'name': 'Monitor', 'price': 319.99}
{'name': 'Desk', 'price': 249.99}
{'name': 'Chair', 'price': 189.99}

Подробнее об управлении количеством возвращаемых документов читайте в MongoDB Limit.

Производительность: используйте индекс для больших коллекций

Для небольших коллекций MongoDB сортирует результаты в памяти. На большой коллекции сортировка в памяти может быть медленной, а если объём превысит 100 МБ — MongoDB вернёт ошибку. Создание индекса по полю сортировки позволяет MongoDB возвращать предварительно упорядоченные данные без сканирования всей коллекции:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["store"]
col = db["products"]

# Create a single-field index on price (ascending)
col.create_index([("price", pymongo.ASCENDING)])

# Queries that sort by price now use the index automatically
results = col.find({}, {"_id": 0, "name": 1, "price": 1}).sort("price", pymongo.ASCENDING)

for doc in results:
    print(doc)

Для сортировки по нескольким полям создайте составной индекс, поля и направления которого совпадают с вашей сортировкой:

col.create_index([
    ("category", pymongo.ASCENDING),
    ("price",    pymongo.ASCENDING),
])

Каждый индекс нужно создавать лишь один раз. Повторные вызовы create_index() с теми же ключами безопасны — PyMongo проверяет, существует ли индекс.

Безопасное хранение строки подключения

В приведённых выше примерах строка подключения жёстко задана в коде для простоты. В реальном приложении храните её в переменной окружения:

import os
import pymongo

client = pymongo.MongoClient(os.environ["MONGODB_URI"])

Задайте переменную в командной оболочке (export MONGODB_URI="mongodb://localhost:27017/") или используйте файл .env с библиотекой, например python-dotenv.

Итоги

ЗадачаШаблон кода
Сортировка по возрастанию.sort("field", pymongo.ASCENDING)
Сортировка по убыванию.sort("field", pymongo.DESCENDING)
Сортировка по нескольким полям.sort([("f1", pymongo.ASCENDING), ("f2", pymongo.DESCENDING)])
Первые N результатов.sort(...).limit(N)
Быстрая сортировка больших данныхСоздайте индекс по полю сортировки

Связанные главы этой серии:

  • MongoDB Find — получение документов с помощью find() и find_one()
  • MongoDB Query — фильтрация с операторами запросов
  • MongoDB Limit — управление количеством возвращаемых документов
  • MongoDB Update — изменение документов в коллекции
Was this page helpful?