Skip to content

Commit 0297de5

Browse files
authored
Merge pull request #100 from jaysalvat/master
Make populate param multilevel
2 parents a744807 + 5f28d3f commit 0297de5

File tree

2 files changed

+108
-18
lines changed

2 files changed

+108
-18
lines changed

src/index.js

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,39 @@ const getProjection = projection => {
146146
return fields;
147147
};
148148

149-
const getPopulation = population =>
150-
population.split(',').map(path => {
151-
return { path };
149+
const getPopulation = population => {
150+
const cache = {};
151+
152+
function iterateLevels(levels, prevLevels = []) {
153+
let populate;
154+
let path;
155+
const topLevel = levels.shift();
156+
prevLevels.push(topLevel);
157+
158+
const cacheKey = prevLevels.join('.');
159+
if (cache[cacheKey]) {
160+
path = cache[cacheKey];
161+
} else {
162+
path = { path: topLevel };
163+
}
164+
cache[cacheKey] = path;
165+
166+
if (levels.length) {
167+
populate = iterateLevels(levels, prevLevels);
168+
if (populate) {
169+
path.populate = populate;
170+
}
171+
}
172+
return path;
173+
}
174+
175+
const populations = population.split(',').map(path => {
176+
return iterateLevels(path.split('.'));
152177
});
153178

179+
return [...new Set(populations)]; // Deduplicate array
180+
};
181+
154182
const getSort = sort => parseUnaries(sort);
155183

156184
const getSkip = skip => Number(skip);
@@ -213,24 +241,30 @@ const getFilter = (filter, params, options) => {
213241
};
214242

215243
const mergeProjectionAndPopulation = result => {
216-
if (result.projection && result.population) {
217-
// Loop the population rows
218-
result.population.forEach(row => {
219-
const prefix = `${row.path}.`;
244+
function iteratePopulation(population, prevPrefix = '') {
245+
population.forEach(row => {
246+
const prefix = `${prevPrefix}${row.path}.`;
220247
Object.keys(result.projection).forEach(key => {
221-
// If field start with the name of the path, we add it to the `select` property
222248
if (key.startsWith(prefix)) {
223249
const unprefixedKey = key.replace(prefix, '');
224-
row.select = {
225-
...row.select,
226-
[unprefixedKey]: result.projection[key],
227-
};
228-
// Remove field with . from the projection
229-
delete result.projection[key];
250+
if (unprefixedKey.indexOf('.') === -1) {
251+
row.select = {
252+
...row.select,
253+
[unprefixedKey]: result.projection[key],
254+
};
255+
delete result.projection[key];
256+
}
230257
}
231258
});
259+
if (row.populate) {
260+
iteratePopulation([row.populate], prefix);
261+
}
232262
});
233263
}
264+
265+
if (result.projection && result.population) {
266+
iteratePopulation(result.population);
267+
}
234268
};
235269

236270
const operators = [

test/index.js

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,21 +349,77 @@ test('populate', t => {
349349
t.deepEqual(res.population, [{ path: 'a' }, { path: 'b' }, { path: 'c' }]);
350350
});
351351

352-
test('populate and projection', t => {
353-
const res = aqp('populate=a,b,c&fields=j,k,l,a.x,a.y,a.z,b.x,b.y,foo.bar');
352+
test('populate (nested)', t => {
353+
const res = aqp('populate=a,b.b1,c.c1.c2');
354354
t.truthy(res);
355-
t.deepEqual(res.projection, { j: 1, k: 1, l: 1, 'foo.bar': 1 });
356355
t.deepEqual(res.population, [
357356
{
358357
path: 'a',
359-
select: { x: 1, y: 1, z: 1 },
358+
},
359+
{
360+
path: 'b',
361+
populate: {
362+
path: 'b1',
363+
},
364+
},
365+
{
366+
path: 'c',
367+
populate: {
368+
path: 'c1',
369+
populate: {
370+
path: 'c2',
371+
},
372+
},
373+
},
374+
]);
375+
});
376+
377+
test('populate (nested, no duplicated)', t => {
378+
const res = aqp('populate=a,a.a1,a.a1.a2');
379+
t.truthy(res);
380+
t.deepEqual(res.population, [
381+
{
382+
path: 'a',
383+
populate: {
384+
path: 'a1',
385+
populate: {
386+
path: 'a2',
387+
},
388+
},
389+
},
390+
]);
391+
});
392+
393+
test('populate (nested) and projection', t => {
394+
const res = aqp(
395+
'populate=a,b.b1,c.c1.c2&fields=j,k,foo.bar,a.x,b.x,b.y,b.b1.x,c.x,c.c1.x,c.c1.c2.x,c.c1.c2.y'
396+
);
397+
t.truthy(res);
398+
t.deepEqual(res.projection, { j: 1, k: 1, 'foo.bar': 1 });
399+
t.deepEqual(res.population, [
400+
{
401+
path: 'a',
402+
select: { x: 1 },
360403
},
361404
{
362405
path: 'b',
363406
select: { x: 1, y: 1 },
407+
populate: {
408+
path: 'b1',
409+
select: { x: 1 },
410+
},
364411
},
365412
{
366413
path: 'c',
414+
select: { x: 1 },
415+
populate: {
416+
path: 'c1',
417+
select: { x: 1 },
418+
populate: {
419+
path: 'c2',
420+
select: { x: 1, y: 1 },
421+
},
422+
},
367423
},
368424
]);
369425
});

0 commit comments

Comments
 (0)