Игнорировать несколько документов с условиями - PullRequest
0 голосов
/ 17 июня 2020

после некоторого агрегирования я придумал следующие документы уровня root.

{ _id:"id_1", isPublished:true, lookingFor:"Banner", name:"Math"},
{ _id:"id_2", isPublished:true, lookingFor:"Banner", name:"English"},
{ _id:"id_3", isPublished:true, lookingFor:"Banner", name:"Science"},
{ _id:"id_4", isPublished:false, lookingFor:"Banner",name:"Health"},
{ _id:"id_5", isPublished:false, lookingFor:"Banner",name:"Religion"}
{ _id:"id_6", isPublished:false, lookingFor:"Featured",name:"Sports"}

Вышеупомянутые документы отсортированы на основе { $sort: { "_id": 1, "isPublished": -1 }}. Мне нужно получить только первый документ баннера, если isPublished:true И lookingFor:"Banner". В противном случае получите все в том же порядке.

Ожидаемый результат:

{ _id:"id_1", isPublished:true, lookingFor:"Banner", name:"Math"},
{ _id:"id_4", isPublished:false, lookingFor:"Banner",name:"Health"},
{ _id:"id_5", isPublished:false, lookingFor:"Banner",name:"Religion"}
{ _id:"id_6", isPublished:false, lookingFor:"Featured",name:"Sports"}

Я не понимаю, как это сделать на уровне ROOT. Пожалуйста, помогите мне. Заранее спасибо

1 Ответ

1 голос
/ 17 июня 2020

Вот несколько подходов к этой проблеме:

  1. В зависимости от масштаба это может не подходить, однако его проще всего реализовать в вашем конвейере, так как его можно было бы легко добавить.

Добавьте либо это:

[
    {
        $facet: {
            one: [
                {
                    $match: {
                        isPublished: true,
                        lookingFor: "Banner"
                    }
                },
                {
                    $limit: 1
                }
            ],
            rest: {
                $match: {
                    $or: [
                        {
                            isPublished: {$ne: true},
                        },
                        {
                            lookingFor: {$ne: "Banner"}
                        }
                    ]
                }
            }
        }
    },
    {
        project: {
            merged: {
                $concatArrays: ["$one", "$rest"]
            }
        }
    },
    {
        $unwind: "$merged"
    },
    {
        $replaceRoot: {
            newRoot: "$merged"
        }
    }
]

, либо следующее:

[
    {
        $group: {
            _id: {pub: "$isPublished", banner: "$lookingFor"},
            roots: {$push: "$$ROOT"}
        }
    },
    {
        $project: {
            roots: {
                $cond: [
                    {
                        $and: [
                            {$eq: ["$_id.pub", true]},
                            {$eq: ["$_id.banner", "Banner"]},
                        ]
                    },
                    {$slice: ["$roots", 1]},
                    "$roots"
                ]
            }
        }
    },
    {
        $unwind: "$roots"
    },
    {
        $replaceRoot: {
            newRoot: "$roots"
        }
    }
]

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

В зависимости от вашей предыдущей агрегации, которую вы не публиковали, может быть лучше просто разделить этот logi c на 2 разных вызова:
db.collection.findOne({isPublished: true, lookingFor: "Banner"})

+

db.collection.find({$or: [{isPublished: {$ne: true}}, {lookingFor: {$ne: "Banner"}})

Опять же, в зависимости от предыдущего logi c это могло бы быть более эффективным. Я также рекомендую вам убедиться, что у вас есть соответствующий индекс для поддержки этого запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...