Nano Hash - криптовалюты, майнинг, программирование

MongoDB получает отдельный объект, вложенный в массив объектов в массиве объектов

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

ВЫБЕРИТЕ ДЕНЬ = 1 ГДЕ _id = 5a3469f22dc3784bdd9a6190 И МЕСЯЦ = 12

Схема модели Mongoose приведена ниже. При необходимости вложенные документы располагаются выше соответствующих родительских документов, причем dailySchedulesSchema является самым высоким:

var dailySchedulesSchema = new mongoose.Schema({
    day: Number,
    dayStart: Number,
    firstBreakStart: Number,
    firstBreakEnd: Number,
    lunchStart: Number,
    lunchEnd: Number,
    secondBreakStart: Number,
    secondBreakEnd: Number,
    dayEnd: Number,
    workDuration: Number
});

var monthlyScheduleSchema = new mongoose.Schema({
    month: {type: Number, required: true },
    dailySchedules: [dailySchedulesSchema]
});

var employeeSchema = new mongoose.Schema({
    name: {type: String, required: true},
    surname: {type: String, required: true},
    email: {type: String, required: true},
    phone: {type: String, required: true},
    occupation: {type: String, required: true},
    status: {type: Boolean, required: true},
    monthlySchedule: [monthlyScheduleSchema]
});

Это запись сотрудника в базе данных, над которой я пытаюсь работать:

"_id" : ObjectId("5a3469f22dc3784bdd9a6190"),
        "name" : "Eric",
        "surname" : "K. Farrell",
        "email" : "[email protected]",
        "phone" : "864-506-7281",
        "occupation" : "Employee",
        "status" : true,
        "monthlySchedule" : [
                {
                        "month" : 12,
                        "dailySchedules" : [
                                {
                                        "day" : 1,
                                        "dayStart" : 480,
                                        "firstBreakStart" : 600,
                                        "firstBreakEnd" : 615,
                                        "lunchStart" : 720,
                                        "lunchEnd" : 750,
                                        "secondBreakStart" : 870,
                                        "secondBreakEnd" : 885,
                                        "dayEnd" : 1020,
                                        "workDuration" : 480
                                },
                                {
                                        "day" : 2,
                                        "dayStart" : 540,
                                        "firstBreakStart" : 630,
                                        "firstBreakEnd" : 645,
                                        "lunchStart" : 750,
                                        "lunchEnd" : 780,
                                        "secondBreakStart" : 870,
                                        "secondBreakEnd" : 885,
                                        "dayEnd" : 1050,
                                        "workDuration" : 480
                                }
                        ]
                }
        ]
}

Сам маршрут для получения одного дня: "/ employee /: employeeid /: month /: day".

Хотя мне удалось получить доступ к родительским документам (например, перечислить всех сотрудников), я не смог перечислить конкретные записи вложенных документов (например, конкретный дневной график для этого сотрудника) - мангуст либо возвращал все существующие дневные расписания в месяце, либо ничего в все:

(...)

  var sendJsonResponse = function(res, status, content){
        res.status(status);
        res.json(content);
    }

(...)

module.exports.empDayReadOne = function(req, res){
    var monthParam = req.params.month;
    var employeeid = req.params.employeeid;
    var dayParam = req.params.day;

    Emp
        .aggregate([
        {$match: {$and: [{'monthlySchedule': {$elemMatch: {$exists: true} } }, {_id: employeeid }] } },
        {$unwind:'$monthlySchedule'}, 
        {$unwind:'$monthlySchedule.dailySchedules'}, 
        {$match:{ $and:[ {'monthlySchedule.dailySchedules.day': dayParam},{'monthlySchedule.month': monthParam} ] } }

        ])
        .exec(function(err, dailySchedule){
            if(dailySchedule){
                sendJsonResponse(res, 200, dailySchedule);
            } else if(err){
                sendJsonResponse(res, 400, err);
                return;
            } else {
                sendJsonResponse(res, 404, {"message": "This day has no schedules added."});
                return;
            }

        });

};

  • какую версию вы используете 02.01.2018
  • Я использую версию 3.2.5 02.01.2018

Ответы:


1

Вы можете попробовать ниже агрегированный запрос.

Приведенный ниже запрос первый $filters monthlySchedule, который возвращает массив с совпадающими Элемент массива month, за которым следует второй фильтр, чтобы получить соответствующий элемент дня в массиве dailySchedules.

$arrayElemAt для преобразования массива с одним элементом в документ.

db.collection_name.aggregate([
  {"$match":{"_id":ObjectId("5a3469f22dc3784bdd9a6190")}},
  {"$project":{
    "dailyschedule":{
      "$arrayElemAt":[
        {"$filter":{
          "input":{
            "$filter":{
              "input":"$monthlySchedule",
              "cond":{"$eq":["$$this.month",12]}
            }
          },
          "cond":{"$eq":["$$this.day",1]
          }
        }},
      0]
    }
  }}
])

Обновленный код Mongoose:

Emp.aggregate([
  {"$match":{"_id":mongoose.Types.ObjectId(employeeid)}},
  {"$project":{
    "dailyschedule":{
      "$arrayElemAt":[
        {"$filter":{
          "input":{
            "$filter":{
              "input":"$monthlySchedule",
              "cond":{"$eq":["$$this.month",monthParam]}
            }
          },
          "cond":{"$eq":["$$this.day",dayParam]
          }
        }},
      0]
    }
  }}
])
02.01.2018
  • Но с $ arrayElemAt вам нужно знать индекс значения в массиве, тогда как приведенный выше пример, похоже, не учитывает это и просто заботится о конкретных ключевых значениях, которые он ищет. Если честно, то это более практичный пример. 04.01.2018
  • $ arrayElemAt с индексом 0 используется для преобразования совпадающего дневного расписания (одно совпадение) в документ. Без arrayElemAt вы получите массив с совпадающим дневным расписанием в нем. Вы можете удалить arrayElemAt, если хотите. $ unwind точно делает то, что я сделал с arrayElemAt, так как всегда выводит одно совпадение ежедневного расписания. Так что $ unwind здесь не требуется. 04.01.2018
  • Метод findOne, похоже, хорошо справляется со своей задачей, не считая возврата всего массива dailySchedules. Есть ли способ подавить остальные индексы? Emp.findOne ({_id: employeeid, monthSchedule.month: monthParam, monthSchedule.dailySchedules.day: dayParam}) 04.01.2018
  • Вот почему мы используем агрегирование, поскольку это невозможно сделать с помощью обычного языка запросов. У вас не работает код агрегации? Это довольно просто: сначала вы фильтруете массив monthSchedule на основе параметра месяца, а затем фильтруете массив daySchedule по параметру дня. Если вы настаиваете на том, чтобы это выполнялось в поисковом запросе, лучшее, что вы можете сделать, - это вывести с сервера массив месячного расписания на основе ежемесячного параметра и выполнить фильтрацию дневного расписания на стороне клиента по параметру дня. Надеюсь, это имеет смысл. 04.01.2018
  • Это определенно работает через mongoose: Emp.aggregate ([{$ match: {_id: mongoose.Types.ObjectId (employeeid)}}, {$ unwind: '$ monthSchedule'}, {$ unwind: '$ monthSchedule.dailySchedules'} , {$ match: {$ and: [{'monthSchedule.month': 12}, {'monthSchedule.dailySchedules.day': 1}]}}]), за исключением monthParam и dayParam, которые я жестко запрограммировал. Как их представить в агрегированном методе? 11.01.2018
  • Попробуйте var monthParam = Number.parseInt(req.params.month) и передайте его агрегатным методам. Как показано в моем ответе, $ unwind не требуется. 11.01.2018
  • Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..