"Объект спецификации этапа трубопровода должен содержать ровно одно поле" при использовании OrderedDict

Я пытаюсь запустить команду aggregate:

request = collections.OrderedDict([
        ("$unwind", "$tags" ),
        ("$group", { "_id" : "$tags" , "count" : { "$sum" : 1 }  } ),
        ("$project", { "_id" : 0, "tag" : "$_id" , "count" : 1 } ),
        ("$sort", { "count" : -1 } ),
        ("$limit", 3 )])

print client.devoxx.talks.aggregate(request)

Но MongoDB отвергает его:

pymongo.errors.OperationFailure: command SON([('aggregate', u'talks'), ('pipeline', [OrderedDict([('$unwind', '$tags'), ('$group', {'count': {'$sum': 1}, '_id': '$tags'}), ('$project', {'count': 1, '_id': 0, 'tag': '$_id'}), ('$sort', {'count': -1}), ('$limit', 3)])])]) failed: exception: A pipeline stage specification object must contain exactly one field.

Мне кажется, что у меня есть каждый агрегатный этап в одном элементе упорядоченного dict.

Ответы

Ответ 1

Это probaby очень специфично для pymongo, но это также очень необязательно, поскольку стандартная форма аргументов для конвейера агрегации на самом деле является массивом и может также просто указываться так, например:

request = [{ "$unwind": "$tags"}, { "$group": { "_id": "$tags" } }]

который всегда будет упорядочиваться по порядку и как таковой не представляет проблемы.

Поэтому нет необходимости использовать OrderedDict.

Возможно, вы запутались в поведении с недавними изменениями в оболочке mongo (от версии 2.6), что позволяет указывать аргументы без переноса в массив. Но JSON, как и некоторые другие языки, ожидает, что их определения "словарь/хэш" будут поддерживать указанный порядок.

Таким образом, использование синтаксиса array/list является еще предпочтительной реализацией.