Как выполнить агрегацию MongoDB

#mongodb #go #aggregation-framework

#mongodb #Вперед #агрегация-фреймворк

Вопрос:

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

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

На самом деле я хотел бы расшифровать мой результат mongo примерно так:

 type exemple struct {
    Orders []Order
    Total int
}
  

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

        bson.D{
                primitive.E{Key: "$facet", Value: bson.D{
                    primitive.E{Key: "orders", Value: []bson.D{
                        {primitive.E{Key: "$skip", Value: p.Skip}},
                        {primitive.E{Key: "$limit", Value: p.Limit}},
                    }},
                    primitive.E{Key: "totalCount", Value: []bson.D{
                        {primitive.E{Key: "$group", Value: bson.D{
                            primitive.E{Key: "_id", Value: nil},
                            primitive.E{Key: "count", Value: bson.D{
                                primitive.E{Key: "$sum", Value: 1},
                            }},
                        }}},
                    }},
                }},
            }
  

Это работает, но только декодирует :

     type exemple struct {
        Orders     []Order                  `bson:"orders" json:"orders"`
        TotalCount []map[string]interface{} `bson:"totalCount" json:"totalCount"`
    }
  

и я должен декодировать с помощью []exemple как:

 var test []exemple
if err = curs.All(r.ctx, amp;test); err != nil {
    return err
}
  

Итак, чтобы получить мои данные, я должен выполнить некоторые fmt.Println(тест [0].totalCount) и это ужасно, поэтому я думаю, что есть лучший способ..

И я думаю, что понимаю a $ project, поэтому я бы воссоздал свои данные схемы, но это так привередливо и не очень приятно.

Я также пробовал это:

 {primitive.E{Key: "$count", Value: "count"}},
{primitive.E{Key: "$skip", Value: p.Skip}},
{primitive.E{Key: "$limit", Value: p.Limit}},
  

Но эта попытка дает для каждых данных ключ подсчета для всех данных в моей БД.

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

——————— РЕДАКТИРОВАТЬ ———————

После тестов я нашел что-то работающее, но если у кого-то есть лучшее решение, я слушаю :

Я добавляю это в свой конвейер :

        bson.D{
            primitive.E{Key: "$facet", Value: bson.D{
                primitive.E{Key: "orders", Value: []bson.D{
                    {primitive.E{Key: "$skip", Value: 10}},
                    {primitive.E{Key: "$limit", Value: 10}},
                }},
                primitive.E{Key: "totalCount", Value: []bson.D{
                    {primitive.E{Key: "$count", Value: "count"}},
                }},
            }},
        }
  

и сопоставить результат агрегатной функции с :

 resp := struct {
    Orders     []Order                  `bson:"orders" json:"orders"`
    TotalCount []map[string]interface{} `bson:"totalCount" json:"totalCount"`
}{}
  

Моя ошибка до этого заключалась в использовании cursor.All() вместо цикла for для cursor.Next(), а затем декодирования (и соответственно) в цикл:

 for curs.Next(r.ctx) {
    if err = curs.Decode(amp;resp); err != nil {
        log.Println(err)
    }
}
  

теперь я могу работать со своим соответствующим, как и с соответствующим.Заказы или соответственно.Общее количество.

Но некоторые вопросы все еще здесь:

  • могу ли я улучшить общее количество? Потому что на самом деле это интерфейс []map[string]{}, поэтому с ним легко работать.

Вывод: [карта [количество: 5]], ожидается: карта [количество: 5]

  • для поиска другой коллекции я добавляю этот []bson.D к моему конвейеру (в моем случае)
 []bson.D{
        {primitive.E{Key: "$lookup", Value: bson.D{primitive.E{Key: "from", Value: "users"}, primitive.E{Key: "localField", Value: "relationShip.customer"}, primitive.E{Key: "foreignField", Value: "_id"}, primitive.E{Key: "as", Value: "relationShip.included.customer"}}}},
        {primitive.E{Key: "$unwind", Value: bson.D{primitive.E{Key: "path", Value: "$relationShip.included.customer"}, primitive.E{Key: "preserveNullAndEmptyArrays", Value: false}}}},
        {primitive.E{Key: "$lookup", Value: bson.D{primitive.E{Key: "from", Value: "users"}, primitive.E{Key: "localField", Value: "relationShip.editor"}, primitive.E{Key: "foreignField", Value: "_id"}, primitive.E{Key: "as", Value: "relationShip.included.editor"}}}},
        {primitive.E{Key: "$unwind", Value: bson.D{primitive.E{Key: "path", Value: "$relationShip.included.editor"}, primitive.E{Key: "preserveNullAndEmptyArrays", Value: false}}}},
    }
  

это работает, НО я добавляю это ПЕРЕД разбиением на страницы, поэтому mongodb ищет всю коллекцию? Можно добавить его после разбиения на страницы для, возможно, повышения производительности?

Комментарии:

1. Вы хотите изменить []map[string]interface{} на int ?

2. Привет @ttrasn Я отредактировал свой вопрос с помощью «решения», возможно, это поможет вам понять