Как сопоставить значения, присутствующие внутри массива, с полем в mongo

#php #mongodb #mongodb-query #aggregation-framework

#php #mongodb #mongodb-запрос #агрегация-фреймворк

Вопрос:

У меня есть этот набор данных в mongo

 {
  _id: {
    question_id: 3
  },
  data: {
    answer: 11,
    count: 114,
    result: [
      {
        _id: 3,
        question: "What is your age group?",
        options: [
          {
            id: 10,
            option: "<18"
          },
          {
            id: 11,
            option: "18-24"
          },
          {
            id: 12,
            option: "24-35"
          },
          {
            id: 13,
            option: ">35"
          }
        ],
        type: "Radio"
      }
    ]
  }
},  

Здесь я хотел бы выполнить equals to проверку между answer и result.options.id , и если значение совпадает, оно должно вернуть result.options.option

Чтобы желаемый результат был

 {
  _id: {
    question_id: 3
  },
  data: {
    answer:'18-24',
    count: 114,
    
  }
},  

До сих пор я пробовал это

 '$project'=>[
  'res'=>[
    '$map'=>[
      'input'=>'$data.result.options',
      'as'=>'dt',
      'in'=>[
        '$cond'=>[
          'if'=>[
            '$eq'=>[
              '$$dt.id',
              '$data.answer'
            ]
          ],
          'then'=>'$$dt.option',
          'else'=>'$$dt.id'
        ]
      ]
    ]
  ]
]  

Любой ключ к пониманию того, что я делаю неправильно. Мой код всегда возвращает оператор else

Ответ №1:

Вы были близки к истине, но есть пара вещей, которые не совсем верны:

 [ '$project'=> [
  'data' => [
    'answer' => [
      '$let' => [
        'vars' => [
          'res' => [
            '$reduce' => [
              'input' => '$data.result.options',
              'initialValue' => [],
              'in' => [ '$concatArrays': [ '$$value', '$$this' ] ]
            ]
          ]
        ],
        'in' => [
          '$arrayElemAt' => [
            '$$res.option',
            [ '$indexOfArray': [ '$$res.id', '$data.answer' ] ]
          ]
        ]
      ]
    ],
    'count' => '$data.count'
  ]
]]
  

Путь к '$data.result.options' фактически находится внутри вложенных массивов, поэтому для того, чтобы любые «операции с массивом» работали с внутренним значением 'options' , вам нужно «сгладить» эту структуру массива в отдельный массив.

Для этого вам следует использовать $reduce наряду с $concatArrays . Это также продемонстрировано в $let блоке, поскольку вы хотите использовать этот «результирующий массив» в некоторых последующих операциях.

Поскольку самый простой способ извлечь одно значение — это найти соответствующий индекс массива через $indexOfArray to 'data.answer' , а затем извлечь 'option' значение из вашего «результирующего массива», обработанного ранее для этого значения, используя $arrayElemAt , конечно, указание на соответствующий «индекс».

$indexOfArray Оператор здесь надежен до тех пор, пока у вас всегда будет ответ, соответствующий 'data.answer' значению, присутствующему в массиве document.