1112 Здесь важен порядок этапов. Вы продвигаете этап $match
после этапа $sample
, который сначала помещает $size
в целые документы, а затем применяет этап $match
к $sample
d
документирует документы.
Итак, наконец, вам нужно продвинуть стадию $sample
после стадии $match
. Порядок должен быть
const limit = Number(req.query.limit || 1);
const difficulty = req.query.difficulty;
const category = req.query.category;
const settings = []
if (difficulty && category) {
settings.push({
$match: {
difficulty: difficulty,
category: category
}
})
} else if (difficulty && category == null) {
settings.push({
$match: {
difficulty
}
})
}
if (difficulty == null && category) {
settings.push({
$match: {
category
}
})
}
setting.push({
$sample: {
size: limit
}
})
console.log(settings);
Question.aggregate(settings)
Что-то, что Вы могли бы рассмотреть, в зависимости от остальной части Вашего дизайна, фабрика, где Ваш абстрактный класс имеет статический метод (или несколько статических методов, в зависимости от того, как Вы реализуете его), который создает соответствующий подкласс и возвращает его как IConverter*. С этим можно выставить только абстрактное определение в заголовочном файле и иметь все определения реального класса и реализации в единственном .cpp файле наряду с реализацией суперкласса. Это становится немного громоздким, если Ваш подкласс является большим, но с меньшими классами он сокращает количество файлов, которыми необходимо управлять.
Но, как другие указали, это - в конечном счете личный выбор. Единственные проблемы производительности были бы связаны с компиляцией; больше cpp файлов могло бы взять (немного) дольше для компиляции, и больше заголовочных файлов могло бы увеличить анализ зависимости. Но нет никакого требования, чтобы каждый заголовочный файл имел соответствие cpp и вице-стих.
На основе комментариев я рекомендовал бы структуру как это:
IConverter.h ==> определение IConverter
Converters.h ==> определения всех подклассов
IConverter.cpp ==> включают IConverter.h и Converters.h, содержат реализацию абстрактной функциональности IConverter (статический метод фабрики и любая наследуемая функциональность)
TextConvter.cpp, ImagerConverter.cpp, и т.д. ==> разделяют cpp файлы для каждого подкласса, каждый содержащий IConverter.h и Converters.h
Это позволяет Вам только включать IConverter.h в любые клиенты, которые используют фабрику и универсальную функциональность. Помещение всех других определений в единственном заголовке позволяет Вам консолидировать, если они - все в основном то же. Отделитесь cpp файлы позволяют Вам использовать в своих интересах преимущества компилятора, упомянутые Brian. Вы могли встроить определения подкласса в заголовочных файлах, как упомянуто, но это действительно не покупает Вас ничто. Ваш компилятор обычно более умен, чем Вы когда дело доходит до оптимизации как встроенный.
Вы, вероятно, получите ответы оба пути.
Я сказал бы для любых тривиальных преобразователей, имение всех их в единственной .h/.cpp паре достаточно и что это - излишество для разделения всех на единственную пару. Я думаю, что компромисс обслуживания большого количества файлов по сравнению с обслуживанием набора методов в единственном файле стоит того в этом случае.
Сложные преобразования, вероятно, заслуживают своих собственных пар файла.
Лучший ответ на это - то, что легче считать. Один долгий исходный файл будет трудным для Вас и других программистов для следования. С другой стороны, многие крошечные (половина полного экрана) исходные файлы так же плохи.
Это не требуется. Это - в основном личный выбор.
Если реализация проста для каждого класса, можно поместить их всех в один.h и один .cpp
Если реализации немного дольше, то это - вероятно, инструмент для очистки для использования отдельного.h и .cpp файла для каждого.
Некоторые преимущества использования другого .h/.cpp для каждого класса:
Вам будут нужны определения реальных классов для создания объектов, таким образом, необходимо будет поместить те определения в.h файл где-нибудь. То, какой файл Вы вставляете их, ваше дело.
Один из основных моментов создания интерфейсного класса - то, так, чтобы клиенты могли быть, зависят от абстрактного интерфейса, а не конкретной реализации, и Вы затем свободны изменить реализацию, не влияя на клиенты.
Помещение конкретных объявлений в тех же заголовочных файлах как объявления интерфейса побеждает это, поэтому теперь при изменении детали реализации реального класса клиенты должны были бы перекомпилировать.
Вы, вероятно, были бы более обеспеченными фабриками использования или указателями функции.
Однако один особенно противный путь, который приходит на ум, использует макрос для объявления реальных классов. Например:
У основания IConverter.h включают следующий макрос
#define DECLARE_CONVERTER_CLASS(CLASS_NAME) \
class CLASS_NAME : public IConverter\
{ \
public: \
CLASS_NAME() {} \
virtual void DoConversion(); \
}; \
Затем в MyConverter1.cpp
DECLARE_CONVERTER_CLASS(MyConverter1)
virtual void MyConverter1::DoConversion()
{
...
}
Фу :-)