2017-01-05 4 views
1

Я хочу создать запрос, который вернет коллекцию доходов за данный год. Моя схема выглядит так:Mongoose условный запрос - case when like statement

export const IncomeSchema = new mongoose.Schema({ 
name: { type: String, required: true }, 
amount: { type: Number, required: true }, 
amountAfterTax: { type: Number, required: false }, 
dateFrom: { 
    month: Number, 
    year: Number 
}, 
dateTo: { 
    month: Number, 
    year: Number 
}, 
isMonthly: { type: Boolean, required: true }, 
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } 
}, { toJSON: { virtuals: true } }); 

// somehow use the req.params.year 
return DB.Incomes.find({ userId: req.user).exec().then(incomes => { 
let incomesForMonth = incomes.filter(income => !income.isMonthly ? (income.dateFrom.year== req.params.year) 
    : (income.dateFrom.year <= req.params.year && income.dateTo.year >= req.params.year) 
}); 

Дело в том, что я хочу, чтобы запрос, чтобы запустить этот путь: - если доход isMonthly то год должен быть равен dateFrom.year - если доход isMonthly то год! должен быть между dateFrom.year и dateTo.year

До сих пор я возвращал все из db и обрабатывал их в памяти, что не является лучшим решением. В SQL Server я бы использовал инструкцию CASE WHEN. Что я могу использовать в мангусте?

+0

Какие у вас версии Mongoose и MongoDB Server? Хотелось бы предложить решение, зависящее от версии MongoDB на вашем сервере, то есть для этого требуется «MongoDB Server 3.4.x: mongoose> = 4.7.3' – chridam

+0

В настоящее время я использую mongoose в' 4.3.6, мой сервер mongoDB запущен на mlab.com, и я думаю, что это '3.2.x' при макс. –

ответ

1

К сожалению, с вашей текущей версией я не могу придумать какое-либо решение для выполнения, которое имеет собственные операторы MongoDB, которые имитируют утверждения/выражения case.

Однако для MongoDB сервера 3.4 и мангуста> = 4.7.3, существует решение, в котором вы можете использовать структуру агрегации, в частности, новый этап $addFields и $switch оператора для таких запросов.

Ступень $addFields эквивалентна стадии $project, что явно указывает все существующие поля ввода документов и добавляет новые поля документов. В вашем случае вам понадобится создать новое поле поля, которое содержит логику фильтра, а затем будет использовано в вашем запросе $match.

$switch Оператор оценивает ряд выражений случая. Когда он находит выражение, которое имеет значение true, $switch выполняет указанное выражение и вырывается из потока управления.

Давайте продемонстрируем это с примером Монго оболочки:

Populate Test Коллекция:

db.test.insert([ 
    { 
     name: "foo", 
     amount: 4, 
     amountAfterTax: 3.2, 
     dateFrom: { 
      month: 11, 
      year: 2016 
     }, 
     dateTo: { 
      month: 2, 
      year: 2017 
     }, 
     isMonthly: true, 
     userId: ObjectId("5864b49ab5a589b63ee298e8") 
    }, 
     { 
     name: "test", 
     amount: 547.74, 
     amountAfterTax: 507.15, 
     dateFrom: { 
      month: 4, 
      year: 2016 
     }, 
     dateTo: { 
      month: 4, 
      year: 2017 
     }, 
     isMonthly: true, 
     userId: ObjectId("5864b49ab5a589b63ee298e8") 
    }, 
     { 
     name: "bar", 
     amount: 56, 
     amountAfterTax: 47.54, 
     dateFrom: { 
      month: 5, 
      year: 2016 
     }, 
     dateTo: { 
      month: 7, 
      year: 2016 
     }, 
     isMonthly: false, 
     userId: ObjectId("5864b49ab5a589b63ee298e8") 
    } 
]) 

Run агрегатного Query

year = 2016; 
db.test.aggregate([ 
    { 
     "$addFields": { 
      "incomesForMonth": { 
       "$switch": { 
        "branches": [ 
         { 
          "case": "$isMonthly", /* same as "case": { "$eq": [ "$isMonthly", true ] }, */ 
          "then": { "$eq": [ "$dateFrom.year", year ] } 
         }, 
         { 
          "case": { "$eq": [ "$isMonthly", false ] }, 
          "then": { 
           "$and": [ 
            { "$lte": [ "$dateFrom.year", year ] }, 
            { "$gte": [ "$dateTo.year", year ] } 
           ] 
          } 
         } 
        ] 
       } 
      } 
     } 
    }, 
    { "$match": { "incomesForMonth": true } } 
]) 

Пример вывод

/* 1 */ 
{ 
    "_id" : ObjectId("586ea7bafedfbcfd0ed15f9a"), 
    "name" : "foo", 
    "amount" : 4.0, 
    "amountAfterTax" : 3.2, 
    "dateFrom" : { 
     "month" : 11.0, 
     "year" : 2016.0 
    }, 
    "dateTo" : { 
     "month" : 2.0, 
     "year" : 2017.0 
    }, 
    "isMonthly" : true, 
    "userId" : ObjectId("5864b49ab5a589b63ee298e8"), 
    "incomesForMonth" : true 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("586ea7bafedfbcfd0ed15f9b"), 
    "name" : "test", 
    "amount" : 547.74, 
    "amountAfterTax" : 507.15, 
    "dateFrom" : { 
     "month" : 4.0, 
     "year" : 2016.0 
    }, 
    "dateTo" : { 
     "month" : 4.0, 
     "year" : 2017.0 
    }, 
    "isMonthly" : true, 
    "userId" : ObjectId("5864b49ab5a589b63ee298e8"), 
    "incomesForMonth" : true 
} 

/* 3 */ 
{ 
    "_id" : ObjectId("586ea7bafedfbcfd0ed15f9c"), 
    "name" : "bar", 
    "amount" : 56.0, 
    "amountAfterTax" : 47.54, 
    "dateFrom" : { 
     "month" : 5.0, 
     "year" : 2016.0 
    }, 
    "dateTo" : { 
     "month" : 7.0, 
     "year" : 2016.0 
    }, 
    "isMonthly" : false, 
    "userId" : ObjectId("5864b49ab5a589b63ee298e8"), 
    "incomesForMonth" : true 
} 
+1

Тогда я буду думать об обновлении db. Благодаря! –

Смежные вопросы