сопоставление полей внутри mongodb

У меня есть следующий документ в mongodb

    {
        "_id" : ObjectId("517b88decd483543a8bdd95b"),
        "studentId" : 23,
        "students" : [
          {
           "id" : 23,
           "class" : "a"
           },
          {
           "id" : 55,
           "class" : "b"
           }
        ]
     }
     {
        "_id" : ObjectId("517b9d05254e385a07fc4e71"),
        "studentId" : 55,
        "students" : [
           {
            "id" : 33,
            "class" : "c"
          }
         ]
     }

Note: Не фактические данные, но схема точно такая же.

Requirement: Поиск документа, который соответствует studentId и students.id(id внутри массива студентов, с помощью одного запроса.

Я пробовал код, как показано ниже

db.data.aggregate({$match:{"students.id":"$studentId"}},{$group:{_id:"$student"}});

Result: Пустой массив. Если я заменю {"students.id":"$studentId"} на {"students.id":33}, он вернет второй документ в показанном выше json.

Можно ли получить документы для этого сценария с помощью одного запроса?


person karthick    schedule 27.04.2013    source источник


Ответы (3)


Если возможно, я бы посоветовал вам установить условие при сохранении данных, чтобы вы могли быстро проверить достоверность (isInStudentsList). Было бы очень быстро сделать такой запрос.

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

db.students.aggregate( 
    {$project: 
        {studentId: 1, studentIdComp: "$students.id"}},  
    {$unwind: "$studentIdComp"}, 
    {$project : { studentId : 1, 
        isStudentEqual: { $eq : [ "$studentId", "$studentIdComp" ] }}}, 
    {$match: {isStudentEqual: true}})

Учитывая ваш пример ввода, вывод будет:

{
    "result" : [
         {
             "_id" : ObjectId("517b88decd483543a8bdd95b"),
             "studentId" : 23,
             "isStudentEqual" : true
         }
    ],
    "ok" : 1
}

Краткое объяснение шагов:

  1. Создайте проекцию документа только с studentId и новым полем с массивом, содержащим только id (чтобы первый документ содержал [23, 55].
  2. Используя эту структуру, $unwind. Это создает новый временный документ для каждого элемента массива в массиве studentIdComp.
  3. Теперь возьмите эти документы и создайте новую проекцию документа, которая по-прежнему имеет studentId и добавляет новое поле с именем isStudentEqual, которое сравнивает равенство двух полей, studentId и studentIdComp. Помните, что на данный момент существует единственный временный документ, содержащий эти два поля.
  4. Наконец, проверьте, что значение сравнения isStudentEqual истинно, и верните эти документы (которые будут содержать исходный документ _id и файл studentId.
  5. Если учащийся был в списке несколько раз, вам может потребоваться сгруппировать результаты по studentId или _id, чтобы предотвратить дублирование (но я не уверен, что вам это нужно).
person WiredPrairie    schedule 27.04.2013

К сожалению, это невозможно ;(

для решения этой проблемы необходимо использовать оператор $where (пример: Найти встроенный документ в mongodb?),

но $where запрещено для использования с платформой агрегации

person Vladimir Muzhilov    schedule 27.04.2013
comment
обратите внимание, что $where не требуется с платформой агрегации (как показывает ответ WiredPrairie, вы можете использовать $project для создания нового поля, а затем использовать $match) - person Asya Kamsky; 29.04.2013
comment
точно @AsyaKamsky, но во многих вопросах я наблюдаю классическую ситуацию: сравнить одно поле и другое поле в некоторой иерархии. я знаю, что проблема вообще в плохой модели данных. многие разработчики создают модель хранения данных, просто копируя + вставляя из реляционных хранилищ;) - person Vladimir Muzhilov; 29.04.2013
comment
Ну, справедливости ради, иногда требования меняются, а вместе с ними и меняющаяся схема означает, что нужно сначала понять новые требования. Такой обходной путь может быть промежуточным шагом при понимании того, что необходимо добавить в схему в долгосрочной перспективе. - person Asya Kamsky; 29.04.2013

person    schedule
comment
Я считаю, что вопрос заключается в том, как найти все документы, в которых условие истинно (выберите документ, в котором список студентов содержит studentId.) - person WiredPrairie; 27.04.2013