Сортировка данных в MоngoBD

Есть данные в базе

"Запчасть": "Цена"
Колесо: 3000
Ручка: 800
Весло: 1500
Дверь:5000

Хочу произвести выгрузку данных отсортировав по цене. Заодно познакомится с регуляркой( если есть вариант получения данный без использования регулярки, тоже рассмотрю)

pattern = re.compile (r'\d')
for i in thing_col.find({'Цена': pattern}).sort("Цена", pymongo.ASCENDING):
    print (i)

но получаю, что сортировка идет по первой цифре, а не по числу т.е. Ручка: 800 отображается после Дверь:5000. Как получить, что бы данные сортировались не по первой цифре. Возможно, надо в питоне самом задать нужный параметр.


Ответы (1 шт):

Автор решения: user3470021

Вероятно, при вставке коллекции в БД поле Цена было записано как строка (String). Т.е., например, вставка выглядела так:

db.so_1154447.insert([
    { "Запчасть": "Колесо", "Цена": "3000" },
    { "Запчасть": "Ручка", "Цена": "800" },
    { "Запчасть": "Весло", "Цена": "1500" },
    { "Запчасть": "Дверь", "Цена": "5000" }
])

В данном случае есть два выхода:

  1. Преобразовать всю базу один раз и применять сортировку в момент выборки данных,
    bulk = collection.initialize_unordered_bulk_op()

    for item in collection.find():
        # преобразуем цену в каждом элементе
        converted = (
            # кастуем ``Цену`` в число
            int(item["Цена"])
            # если цена не является числом, то обнуляем её
            if item["Цена"].isdigit() else 0
        )
        # добавляем в очередь операцию для обновления поля ``Цена``, указывая при этом ID
        bulk.find({"_id": item["_id"]}).update({'$set': {"Цена": converted}})

    # выполняем все операции обновления
    bulk.execute()

    from pprint import pprint
    pprint(
        # применяем поиск с сортировкой на стороне БД
        [item for item in collection.find().sort("Цена", pymongo.ASCENDING)]
    )
  1. Каждый раз при выборках учитывать, что цена представлена строкой и сортировать в python-коде.
    from pprint import pprint
    pprint(
        # сортируем при помощи python
        sorted(
            # получаем данные в произвольном порядке из БД
            [item for item in collection.find()],
            # по полю ``Цена``
            key=lambda item: (
                # кастуем цену в число
                int(item["Цена"])
                # если цена не является числом, то учитываем её как нуль
                if item["Цена"].isdigit() else 0
            )
        )
    )

Оба подхода уместны. Например, если Вам нужно один раз избавиться от проблемы и размер базы несущественный, то выбирайте первый вариант.
Если у Вас огромная база и нужно сначала отобрать данные по критерию (сузить выборку), а уже потом сортировать, то можно использовать второй вариант.

→ Ссылка