MongoDB запрашивает несколько вложенных документов - PullRequest
0 голосов
/ 09 июля 2020

Моя структура данных MongoDB выглядит следующим образом:

{
  users: [{
    userref: "User1",
    results: [{
      testref: "TEST1",
      history: [{
        score: 10
      }, {
        score: 15
      }]
    }, {
      testref: "TEST2",
      history: [{
        score: 2
      }, {
        score: 1
      }]
    }]
  }]
}

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

Что мне нужно сделать, так это "вернуть ссылку на пользователя для всех пользователей, у которых самая последняя оценка за TEST1 равна X, а самая последняя оценка за TEST2 - Y" . Пользователи, не прошедшие тот или иной из этих тестов, не подлежат возврату. Под «самым последним» я подразумеваю последнее в массиве.

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

Это то, что я пробовал до сих пор, и он работает, но он соответствует только условию, где TEST1 = 15, и я также хотел бы, чтобы он соответствовал условию TEST2 = 1.

[{$unwind: {
  path: '$results’,
  preserveNullAndEmptyArrays: false
}}, {$match: {
  'results.testref': 'TEST1'
}}, {$project: {
  results: 1,
  userref: 1,
}}, {$replaceRoot: {
  newRoot: {
    $mergeObjects: [
      {
        userref: '$userref'
      },
      '$results'
    ]
  }
}}, {$project: {
  userref: 1,
  history: {
    $slice: [
      '$history',
      -1
    ]
  }
}}, {$match: {
  'history.score': 15
}}, {$project: {
  userref: 1,
}}]

Спасибо

1 Ответ

1 голос
/ 09 июля 2020

Чтобы соответствовать обоим условиям,

db.getCollection('test2').aggregate([{"$unwind":"$users"}, {$unwind:"$users.results"}, 
{$project:
     {"lastScore": 
        {$slice:
            ["$users.results.history", -1]
        },
     "users.userref":1,
     "users.results.testref":1
    }
},
{
    $match:{"$or":[{
      $and:[
        {"users.results.testref":"TEST1"},
        {"lastScore.0.score":15}
      ]},
      {
      $and:[
        {"users.results.testref":"TEST2"},
        {"lastScore.0.score":1}
      ]}
      ]
    }
},
{
    $group:{
        "_id":{"_id":"$_id","userref":"$users.userref"},
        "data":{$push:{"tests":"$users.results.testref", "userref":"$users.userref"}}
    }
},
{
    $project:{
        "_id":1,
        "validUser":{
        "$filter":{
            "input":"$data",
            "as":"data",
            "cond":{$or:[{$eq:["$$data.tests","TEST1"]}, {$eq:["$$data.tests","TEST2"]}]}
        }}
    }
},
{
    $project:{
        "_id.userref":1
    }
}
])

Что делает запрос:

  1. Разматывать пользователей
  2. Разматывать результаты
  3. Получить последняя часть оценки вместе с ссылкой пользователя, тестовая ссылка
  4. Проверить наличие необходимых условий
  5. Сгруппировать обратно по ссылке пользователя вместе с do c id
  6. Проверить выполнение двух условий используя $ filte
  7. Project userref

Вывод:

/* 1 */
{
    "_id" : {
        "userref" : "User1"
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...