Учитывая следующую схему:
const usersSchema = Schema({
image : {type: String},
firstName: {type: String},
lastName : {type: String},
club : {type: String, ref: 'clubs'}
}, {strict: true, useNestedStrict: true});
const Users = mongoose.model('Users', usersSchema);
const clubsSchema = Schema({
image: {type: String},
name : {type: String},
}, {strict: true, useNestedStrict: true});
const clubs = mongoose.model('clubs', clubsSchema);
Итак, у вас есть список пользователей, и каждый пользователь принадлежит к клубу, который сохраняется как ссылка на поддокумент.
Теперь у меня есть сводный запрос для поиска.
(примечание: мой фактический запрос и схема намного сложнее, со многими поддокументами, я упростил их для этого поста)
let activePage = 0;
let resultsPerPage = 10;
let results = await Users.aggregate([
{$sort: {firstName: 1, lastName: 1, club.name: 1}},
{$lookup: {from: 'clubs', localField: 'club', foreignField: '_id', as: 'club'}},
{$unwind: "$club"},
{$project: {"_id": true, "image": true, "firstName": true, "lastName": true, "club._id": true, "club.name": true, "club.image": true}},
{$match: {firstName: "Dave"}},
{$group: {
_id : '$_id',
image : {$first: "$image"},
firstName: {$first: "$firstName"},
lastName : {$first: "$lastName"},
club : {
$first: {
_id : "$club._id",
name : "$club.name",
image: "$club.image"
}
}
}
}},
{$facet: {count: [{$count: "count"}], records: [{$skip: activePage}, {$limit: activePage * resultsPerPage}]}}
]);
Когда я запускаю запрос, я получаю следующие (примерные) данные:
results.count[0].count // 4
results.records:
_id | image | firstName | lastName | club._id | club.name | club.image
111 | <data> | Dave | Burns | c123 | admins | <data>
222 | <data> | Dave | Simpson | c123 | admins | <data>
333 | <data> | Dave | Sanchez | c123 | admins | <data>
444 | <data> | Dave | Smith | c456 | losers | <data>
До этого момента все работало точно так, как задумано.
Но мне не нравится тот факт, что данные клуба повторяются для каждой записи ... идентификатор клуба, имя и изображение дублируются 3 раза. Boo!
Что я хочу сделать, так это иметь его, чтобы я сохранил club._id в данных записи, а затем получил другое свойство в объекте результатов, который содержал бы соответствующие клубы.
Я хочу закончить с этим:
results.count[0].count // 4
results.records:
_id | image | firstName | lastName | club._id
111 | <data> | Dave | Burns | c123
222 | <data> | Dave | Simpson | c123
333 | <data> | Dave | Sanchez | c123
444 | <data> | Dave | Smith | c456
results.clubs:
_id | image | name
c123 | <data> | admins
c456 | <data> | losers
Таким образом, данные клуба не дублируются, и, таким образом, информация, передаваемая с сервера клиенту, значительно уменьшается. Затем на стороне клиента, когда я отображаю список, я могу сделать перекрестную ссылку, найти клуб для каждого пользователя и отобразить соответствующие данные.
Вопрос:
Есть ли способ в агрегированном запросе сделать это?
Я уже знаю, что могу сделать заполнение после факта или другого "после факта" поиска и запросов и тому подобного - но я не хочу этого делать. Я бы предпочел, чтобы все было сделано за один раз, потому что я обнаружил, что когда все сказано и сделано, это гораздо быстрее. Кроме того, в запрос встроена нумерация страниц и тому подобное ... Я не хочу повторять результаты после выполнения запроса, чтобы заполнить отсутствующие данные, если я могу помочь.
Кто-нибудь знает, можно ли это сделать?