2016-04-22 6 views
4

У меня есть коллекция с ниже структуры данных:питон - сортировка MongoDB по стоимости одной ключевой

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

Я хочу, чтобы иметь возможность сортировать их по значению category, указав который приходит первым. Например, сортировка запроса в порядке B-> C-> A, результат даст:

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

Есть ли хороший способ сделать это с помощью API Монго запроса? Я использую mongoengine

+0

Это возможно дубликат [этот вопрос] (https://stackoverflow.com/questions/34714910/how-can-i-get- top-n-buckets-for-an-aggregation-and-all-other-buckets-together-in) Я не могу проголосовать за закрытие, потому что ответ на этот вопрос не одобрен или не принят, поэтому добавил ответ. – styvane

ответ

2

Лучший способ сделать это s использует метод .aggregate() и условный оператор $cond добавить вес к документам в $project этапе затем использовать оператор $sort агрегации для сортировки документов по весу.

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 с использованием 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}] 
1

Я думаю, что до сих пор не представляется возможным обеспечить пользовательскую функцию сортировки в MongoDB:

вы можете, хотя, как обходной путь, сортировки в Python, картографирование категорий, которые будут фактически использоваться для сортировки документов:

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"]))) 
+0

это будет работать :) – tropicalfish

+0

На самом деле это * джира * довольно старая. Интересно, почему он все еще открыт, потому что с версии MongoDB 2.6 вы можете использовать оператор ['$ cond'] (https://docs.mongodb.org/manual/reference/operator/aggregation/cond/) для выполнения этой серверной , В любом случае это решит проблему, но будет менее эффективно, чем решение, использующее встроенный API, закодированный в C++ – styvane

+0

@ user3100115 о, ничего себе, не знал этого. Отличный ответ! Благодарю. – alecxe

Смежные вопросы