MGO Pipe с запросом $ lookup не будет прикреплять соответствующие документы из «объединенной» коллекции - PullRequest
3 голосов
/ 03 мая 2019

Мои модели

type (
    //Category implements item category in database
    Category struct {
        ID          bson.ObjectId `bson:"_id,omitempty" json:"id"`
        Name        string        `bson:"name" json:"name" form:"name" valid:"Required"`
        IsActive    bool          `bson:"is_active" json:"is_active" form:"is_active" valid:"Required"`
        Slug        string        `bson:"slug" json:"slug"`
        Icon        string        `bson:"icon" json:"icon" form:"icon"`
        SidebarIcon string        `bson:"sidebar_icon" json:"sidebar_icon" form:"sidebar_icon"`
        Parent      bson.ObjectId `bson:"parent,omitempty" json:"parent,omitempty" form:"parent"`
        CreatedAt   time.Time     `bson:"created_at" json:"-"`
        UpdatedAt   time.Time     `bson:"updated_at" json:"-"`
        IsDeleted   bool          `bson:"is_deleted" json:"-"`
    }
)

Мой запрос на получение коллекции:

categories := []models.Category{}

f := func(collection *mgo.Collection) error {
        query := []bson.M{
            {
                "$match": bson.M{
                    "is_deleted": bson.M{
                        "$ne": true,
                    },
                },
            },
            {
                "$sort": bson.M{
                    orderBy: pipeOrder,
                },
            },
            {
                "$limit": limit,
            },
            {
                "$skip": skip,
            },
            {
                "$lookup": bson.M{
                    "from":         "categories",
                    "localField":   "_id",
                    "foreignField": "parent",
                    "as":           "parentlist",
                },
            },
        }

        return collection.Pipe(query).All(&categories)

Цель : получить все категории вместе с их родителями, если их родительский идентификатор совпадает содин из документов в коллекции.

Проблема : извлечены все категории, но отсутствует объединенный атрибут родительского списка

Стек : Mgo для взаимодействияс БД и Голангом версия 1.8

1 Ответ

1 голос
/ 03 мая 2019

В вашей совокупности вы ищите родителей, и они будут храниться в поле с именем parentlist.И вы пытаетесь распаковать результаты в срез Category, но у типа Category нет поля, которое бы соответствовало parentlist.Таким образом, это поле будет «потеряно» в процессе демаршалинга.

Есть много способов получить дополнительные parentlist, некоторые из возможностей подробно описаны в этом ответе: Агрегация Mgo: как использовать повторнотипы моделей для запроса и демарширования «смешанных» результатов?

Один из вариантов - использовать структуру-обертку, например, такую:

type CategoryWithParents struct {
    Category models.Category    `bson:",inline"`
    Parents  []*models.Category `bson:"parentlist"`
}

И демонтировать в кусок этого:

var results []CategoryWithParents

err := collection.Pipe(query).All(&results)

Получат все родители.

Если для всех категорий может быть не более одного родителя, вы можете изменить агрегацию на $unwind, parentlist и Parentsможет быть одним *model.Category вместо среза:

type CategoryWithParents struct {
    Category       models.Category  `bson:",inline"`
    OptionalParent *models.Category `bson:"parentlist"`
}

var results []CategoryWithParents

f := func(collection *mgo.Collection) error {
    query := []bson.M{
        {
            "$match": bson.M{
                "is_deleted": bson.M{
                    "$ne": true,
                },
            },
        },
        {
            "$sort": bson.M{
                orderBy: pipeOrder,
            },
        },
        {"$limit": limit},
        {"$skip": skip},
        {
            "$lookup": bson.M{
                "from":         "categories",
                "localField":   "_id",
                "foreignField": "parent",
                "as":           "parentlist",
            },
        },
        {
            "$unwind": bson.M{
                "path":                       "parentlist",
                "preserveNullAndEmptyArrays": true,
            },
        },
    }

    return collection.Pipe(query).All(&results)
}
...