2015-09-17 4 views
2

у меня есть некоторые документы, как:MongoDB сортировать по сумме указанного объекта внутри внутреннего массива

{ 
    "_id" : 1, 
    "inner_array" : [ 
     { 
      "object_value" : 1, 
     }, 
     { 
      "object_value" : 2, 
     }, 
     { 
      "object_value" : 1, 
     }, 
    ] 
} 

{ 
    "_id" : 2, 
    "inner_array" : [ 
     { 
      "object_value" : 1, 
     }, 
     { 
      "object_value" : 1, 
     }, 
     { 
      "object_value" : 1, 
     }, 
    ] 
} 

В первом документе Есть два объекта внутри «inner_array» с «object_value» 1. Теперь я хочу для сортировки документов по общему количеству объектов внутри «inner_array», чье «object_value» равно 1. Так, как и в примере выше, ключ сортировки первого документа равен 2, а второй - 3.

Я делаю некоторые но по-прежнему не может определить способ, а не получать все документы и писать код для фильтрации и сортировки. Как я могу это сделать в инструкции по родному монго?

Заранее благодарен!

ответ

2

Вы можете использовать инфраструктуру MongoDB Aggregation, чтобы получить результаты запроса, которые вы указали.

Структура агрегации позволяет разбивать вашу обработку на один или несколько этапов, где каждый этап выполняет некоторые основные работы, такие как фильтрация, группировка, преобразование результатов на определенном этапе. aggregation stage operators поддерживают эту обработку.


В результате один способ приблизиться ваш запрос с помощью агрегации и создания следующих этапов:

  1. Unwind ваш inner_array массив. Это облегчит возможность подсчета inner_array.object_value, равного 1.
  2. Group Ваши результаты, чтобы мы получили общее количество inner_array.object = 1 за документ.

    При расчете totalCount, то $sum имеет место только для inner_array.object_value элементов, которые имеют значение 1.

    Также в группе я добавляю inner_array к результатам этапа, так как я предполагаю, что вы хотите видеть все элементы документа в конечном наборе результатов.

  3. Sort результаты этапа по totalCount в порядке возрастания (использование для -1 порядке убывания).

  4. Project Результаты, удаляющие поле totalCount из ваших окончательных результатов.


Если ваша коллекция называется yourcollection то это то, что ваш агрегация запрос будет выглядеть так, как описано в предыдущих шагах.

db.yourcollection.aggregate([ 
    { "$unwind" : "$inner_array" }, 
    { "$group" : { 
     "_id" : "$_id", 
     "totalCount" : { 
      "$sum" : { 
       "$cond" : { 
        "if" : { "$eq" : [ "$inner_array.object_value", 1 ] }, 
        "then" : 1, 
        "else" : 0 
       } 
      } 
     }, 
     "inner_array" : { 
      "$push" : { 
       "object_value" : "$inner_array.object_value" 
      } 
     } 
    }}, 
    { "$sort" : { "totalCount" : 1 } }, 
    { "$project" : { 
      "inner_array" : 1 
    }} 
]) 

Я полагаю, что при выполнении запроса, начиная с первым этапом только ($unwind), так что вы можете увидеть, что производит каждый этап. Добавьте следующий этап, чтобы увидеть, как он изменяет ваши результаты, а затем следующий и т. Д.

Наконец, этот запрос не учитывает производительность, поскольку он не находится в непосредственной близости от этого вопроса. Просто знайте, что если у вас большой набор данных, вы можете воспользоваться индексами и изменить свой запрос на агрегацию, чтобы использовать эти индексы.

+0

Благодарим за ответ и большое предложение! После того, как я построю этап '$ unwind', я могу видеть, что у меня есть, и построить другие этапы самостоятельно. Поэтому, наконец, я получаю следующее: 'db.mycollection.aggregate ([ {$ unwind: '$ inner_array'}, {$ match: {'inner_array.object_value': 1}}, {$ group: {_id: '$ _id', totalCount: {$ sum: 1}}}, {$ sort: {totalCount: 1}} ]) ' –

+0

@KevinXi Я рад, что мое предложение помогло. Ваш обновленный агрегированный запрос является идеальным. – whyceewhite

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