mongodb агрегированные встроенные значения документа

Я борюсь с некоторыми функциями агрегирования в mongodb.

Скажем, у меня есть такие документы

 [
 {
    _id: "1",
    periods: [
      {
         _id: "12",
         tables: [
           {
              _id: "121",
              rows: [
                  { _id: "1211", text: "some text"},
                  { _id: "1212", text: "some other text"},
                  { _id: "1213", text: "yet another text"},

              ]
           }
         ]
      },
      {
         _id: "13",
         tables: [
           {
              _id: "131",
              rows: [
                  { _id: "1311", text: "different text"},
                  { _id: "1312", text: "Oh yeah"}                      
              ]
           }
         ]
      }
    ]
 },
 {
    _id: "2",
    periods: [
      {
         _id: "21",
         tables: [
           {
              _id: "212",
              rows: [
                  { _id: "2121", text: "period2 text"},
                  { _id: "2122", text: "period2 other text"},
                  { _id: "2123", text: "period2 yet another text"},

              ]
           }
         ]
      }
    ]
 }
 ]

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

например, объединить все тексты для верхнего _id 1. Это будет означать, что я хочу получить все тексты в обоих поддеревьях периода.

ожидаемый результат будет следующим:

агрегированная фильтрация текстов по _id: 1

[
   "some text",
   "some other text",
   "yet another text",
   "different text",
   "Oh yeah"
]

агрегированная фильтрация текстов по _id: 2

[
  "period2 some text",
  "period2 some other text",
  "period2 yet another text"
]

Пока мне удалось собрать все тексты, но в итоге они оказались в нескольких массивах, и мне не удалось отфильтровать их по идентификатору с помощью $ match,

Мой текущий агрегатный запрос выглядит так

[ 
    { "$project" : { "text" : "$periods.tables.rows.text" , "_id" : "$_id"}},
    { "$unwind" : "$text"},
    { "$group" : { "_id" : "$_id" , "texts" : { "$addToSet" : "$text"}}},
    { "$project" : { "_id" : 0 , "texts" : 1}} 
]

Это дает мне результат, ищущий что-то вроде этого

{ "texts" : [ 
        [ [ "Some text" , "Some other text" , "yet another text"] , [ "different text" , "oh yeah" ] ],
        [ [ "period2 some text", "period2 some other text", "period2 yet another text"]]
    ]}

Если я добавлю $ match: {_id: 1}, результаты не будут возвращены.

Может ли кто-нибудь помочь мне с этим или указать мне, как его решить. Я искал ресурсы, но, похоже, не нашел хорошей документации о том, как использовать эти агрегатные функции. Документы mongodb используют только простые документы.

PS Я знаю, что могу сделать это с помощью mapreduce, но надеялся, что смогу использовать для этого агрегатную функцию.


person Tommy    schedule 13.09.2013    source источник


Ответы (1)


Unwind опускается только на один уровень, поэтому вы должны вызывать столько раз, сколько уровней у вас есть, если вы делаете это, как хотите.

[ 
    { "$project" : { "text" : "$periods.tables.rows.text" , "_id" : "$_id"}},
    { "$unwind" : "$text"},
    { "$unwind" : "$text"},
    { "$unwind" : "$text"},
    { "$group" : { "_id" : "$_id" , "texts" : { "$addToSet" : "$text"}}},
    { "$project" : { "_id" : 0 , "texts" : 1}} 
]

Он будет работать так, как вы ожидаете.

person attish    schedule 13.09.2013