Сортировка данных в 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 шт):
Вероятно, при вставке коллекции в БД поле Цена было записано как строка (String).
Т.е., например, вставка выглядела так:
db.so_1154447.insert([
{ "Запчасть": "Колесо", "Цена": "3000" },
{ "Запчасть": "Ручка", "Цена": "800" },
{ "Запчасть": "Весло", "Цена": "1500" },
{ "Запчасть": "Дверь", "Цена": "5000" }
])
В данном случае есть два выхода:
- Преобразовать всю базу один раз и применять сортировку в момент выборки данных,
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)]
)
- Каждый раз при выборках учитывать, что цена представлена строкой и сортировать в
python-коде.
from pprint import pprint
pprint(
# сортируем при помощи python
sorted(
# получаем данные в произвольном порядке из БД
[item for item in collection.find()],
# по полю ``Цена``
key=lambda item: (
# кастуем цену в число
int(item["Цена"])
# если цена не является числом, то учитываем её как нуль
if item["Цена"].isdigit() else 0
)
)
)
Оба подхода уместны. Например, если Вам нужно один раз избавиться от проблемы и размер базы несущественный, то выбирайте первый вариант.
Если у Вас огромная база и нужно сначала отобрать данные по критерию (сузить выборку), а уже потом сортировать, то можно использовать второй вариант.