python – ordena mongodb por el valor de una tecla

Tengo una colección con la siguiente estructura de datos:

[{name: "123", category: "A"}, {name: "456", category: "B"}, {name: "789", category: "A"}, {name: "101", category: "C"}] 

Quiero poder clasificarlos según el valor de la category , especificando qué es lo primero. Por ejemplo, al ordenar la consulta en el orden de B-> C-> A, el resultado arrojaría:

 [{name: "456", category: "B"}, {name: "101", category: "C"}, {name: "123", category: "A"}, {name: "789", category: "A"}] 

¿Hay alguna buena manera de hacerlo con la API de consulta de Mongo? Estoy usando mongoengine

La mejor manera de hacerlo es usar el método .aggregate() y el operador condicional $cond condicional para agregar un peso a sus documentos en la etapa $project luego usar el operador de agregación $sort para clasificar sus documentos por peso .

 pipeline = [{'$project': {'category': 1, 'name': 1, 'w': {'$cond': [{'$eq': ['$category', 'B']}, 1, {'$cond': [{'$eq': ['$category', 'C']}, 2, 3] }] } }}, {'$sort': {'w': 1}} ] Model.aggregate(*pipeline) 

Demo usando PyMongo :

 >>> import pprint >>> import pymongo >>> client = pymongo.MongoClient() >>> collection = client['test']['collection'] >>> pipeline = [{'$project': {'category': 1, ... 'name': 1, ... 'w': {'$cond': [{'$eq': ['$category', 'B']}, ... 1, ... {'$cond': [{'$eq': ['$category', 'C']}, ... 2, ... 3] ... }] ... } ... }}, ... {'$sort': {'w': 1}} ... ] >>> pprint.pprint(list(collection.aggregate(pipeline=pipeline))) [{'_id': ObjectId('571caa930e4f55302502a361'), 'category': 'B', 'name': '456', 'w': 1}, {'_id': ObjectId('571caa930e4f55302502a363'), 'category': 'C', 'name': '101', 'w': 2}, {'_id': ObjectId('571caa930e4f55302502a360'), 'category': 'A', 'name': '123', 'w': 3}, {'_id': ObjectId('571caa930e4f55302502a362'), 'category': 'A', 'name': '789', 'w': 3}] 

Creo que todavía no es posible proporcionar una función de clasificación personalizada en MongoDB:

Sin embargo, puede, como solución alternativa, ordenar en Python, asignando categorías a valores numéricos que realmente se usarían para ordenar los documentos:

 from pprint import pprint weights = { "A": 2, "B": 0, "C": 1 } docs = db.col.find() pprint(sorted(docs, key=lambda item: weights.get(item["category"])))