Как отсортировать результаты по месяцам в MongoDB

У меня есть коллекция contacts с документами, подобными этому:

{ Name: "John Doe", BirthDate: ISODate("1980-03-12T00:00:00.000Z"), Address: "..." }

Мне нужно получить все документы, отсортированные по месяцу части поля Дата рождения. Результат должен включать все поля документа. Идея состоит в том, чтобы показать пользователю, у каких контактов есть день рождения в каждом месяце.

Я пытался создать агрегацию, но не могу понять, как сортировать поле Дата рождения с помощью оператора $month.

Может быть, я могу использовать $group, но как мне показать все поля документа?


person Yev    schedule 27.02.2014    source источник


Ответы (1)


Что ж, в этом есть хитрость, и в зависимости от того, что вы хотите сделать, вы можете использовать несколько подходов. Самый простой способ — использовать $project в конвейер агрегации.

Я работаю с подмножеством того, что у меня есть из ваших областей, но общая концепция заключается в том, чтобы определить их все в $project и дополнительное поле:

db.collection.aggregate([

    // You probably want to do some matching first

    // Project your altered document form with a *new* field for "month"
    {"$project": {
        "Name": 1,
        "BirthDate": 1,
        "Address": 1,
        "month": { "$month": "$BirthDate" }               // Extra field for "month"
    }},

    // Sort by your month value
    {"$sort": { "month": 1 }},

    // Then just clean the extra part from your projection
    // ( if you need to )
    {"$project": {
        "Name": 1,
        "BirthDate": 1,
        "Address": 1,
    }},

])

Если вам нужно сделать что-то более сложное, которое будет включать какую-либо форму группировки или другие операции, тогда сохраните документ в _id, пока вы выполняете такие действия, как группировка в весь документ:

db.collection.aggregate([

   // Save your document in the `_id` field
    {"$project": {
        _id: {
            _id: "$_id",
            "Name": 1,
            "BirthDate": 1,
            "Address": 1
        }
    }},

Здесь был еще один пример использования этого:

Как вернуть исходный документ после объединения

person Neil Lunn    schedule 27.02.2014
comment
Я думал пойти по этому пути, и ваш пример великолепен. Но тот факт, что мне нужно проецировать все поля вручную, меня беспокоит. Что, если позже я добавлю в документы дополнительные поля или удалю некоторые из них, мне придется найти все агрегаты, которые делают проекцию на эту коллекцию, и исправить их. Я надеюсь найти способ включить все поля автоматически. - person Yev; 27.02.2014
comment
@Yev Аноин да. Начиная с версии 2.6 будет использоваться переменная $$ROOT, которая является псевдонимом для всего документа на данном этапе конвейера. На данный момент нет другого способа обойти это. - person Neil Lunn; 27.02.2014
comment
@Yev В принципе, я обычно не кодирую эти операторы (кроме случаев, когда играю/разрабатываю), но они генерируются в реальном коде. Вот как я отношусь к тому, что вы описываете. - person Neil Lunn; 27.02.2014
comment
Хорошо, это хорошо знать. Тогда я сделаю это вручную и подожду 2.6. Не могли бы вы опубликовать ссылку на документацию $$ROOT? Я не могу найти его на сайте MongoDB. - person Yev; 27.02.2014
comment
Спасибо, я видел этот документ. Я хотел бы игру, но она нужна мне довольно скоро, RC для меня :( Я не уверен, выпустят ли они 2.6 в марте или перейдут сразу на 2.7 позже. - person Yev; 27.02.2014
comment
@Yev 2.6 - это релиз. Ветка Dev была 2.5.x. Он будет готов, когда будет готов. ошибка JIRA для $$ROOT - person Neil Lunn; 27.02.2014