Skip to content

Commit 628fbee

Browse files
committed
coherent references in production
1 parent e3f47ed commit 628fbee

1 file changed

Lines changed: 39 additions & 21 deletions

File tree

src/routes/references/index.js

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,45 @@ const wholeReferenceResponse = handler({
1717
const database = await getDatabase(request);
1818
// Get the requested reference configuration
1919
const referenceName = request.params.reference;
20+
const reference = REFERENCES[referenceName];
21+
if (!reference) return {
22+
headerError: NOT_FOUND,
23+
error: `Unknown reference "${referenceName}". Available references: ${availableReferences}`
24+
};
25+
// Get a list with all reference ids which are to be returned according to the available projects
26+
// Note that less references are to be returned if this is the production API
27+
const projectQuery = database.getProjectQuery();
28+
const distinctResult = await database.projects.distinct(
29+
reference.projectIdsField, projectQuery);
30+
let availableReferenceIds = new Set(distinctResult);
31+
// Get the number of references to be matched with the current query
32+
const referencesCount = availableReferenceIds.length;
33+
// Set the target mongo collection
34+
const collection = database[referenceName];
2035
// Get the requested query, if any
2136
const query = request.query.query;
22-
const parsedQuery = (query && JSON.parse(query)) || {};
37+
// If a query was passed then filter references and get the remaining reference ids
38+
if (query) {
39+
// Parse the query
40+
const parsedQuery = JSON.parse(query);
41+
// Query all references and get only their reference ids
42+
const cursor = await collection.find(parsedQuery)
43+
.project({ _id: false, [reference.idField]: true });
44+
const filteredReferenceIds = new Set(cursor.map(ref => ref[reference.idField]));
45+
// Keep only reference ids which are both available and filtered
46+
availableReferenceIds = availableReferenceIds.intersection(filteredReferenceIds);
47+
}
48+
// Sort the available reference ids
49+
const sortedReferenceIds = Array.from(availableReferenceIds).sort();
2350
// Check if we are to return only the available ids
2451
// If so then there is no need for pagination or projections
2552
// LORE: This was the original behaviour of this endpoint
2653
const justIds = request.query.justids;
2754
const returnJustIds = justIds !== undefined && justIds !== 'false';
28-
if (returnJustIds) return await database.getReferenceAvailableIds(referenceName, parsedQuery);
55+
if (returnJustIds) return sortedReferenceIds;
2956
// Otherwise we must paginate and handle possible projections
3057
// Set the projection object for the mongo query
31-
const projector = {};
58+
const projector = { _id: false };
3259
// Handle when it is a mongo projection itself
3360
// Note that when a projection is requested the project data is not formatted
3461
let projection = request.query.projection;
@@ -46,29 +73,20 @@ const wholeReferenceResponse = handler({
4673
Object.assign(projector, objectProjection);
4774
}
4875
}
49-
// Set the target mongo collection
50-
const collection = database[referenceName];
51-
// Get the number of references to be matched with the current query
52-
const referencesCount = await collection.countDocuments(parsedQuery);
53-
// Finally, perform the mongo query
54-
// WARNING: If the query is wrong it will not make the code fail until the cursor in consumed
55-
// e.g. cursor.toArray()
56-
const cursor = await collection.find(parsedQuery).project(projector);
57-
// Handle the pagination
58-
// Get the limit of references to be returned
76+
// Do the pagination manually
77+
// Get the skip (page) and limit of references to be returned
5978
// If the query has no limit then use a defualt value
6079
// If the query limit is grater than the limit then set it as the limit
6180
// If the limit is negative (which makes not sense) it is set to 0
6281
// This is defined in the src/server/index.js script
63-
let limit = request.query.limit;
82+
const skip = request.skip;
83+
const limit = request.query.limit; // The limit will never be greater than 100
84+
const paginatedReferenceIds = sortedReferenceIds.splice(skip, limit);
85+
const paginatedReferencesQuery = { [reference.idField]: { $in: paginatedReferenceIds } };
86+
// Finally, perform the final mongo query
87+
const cursor = await collection.find(paginatedReferencesQuery).project(projector);
6488
// Finally consume the cursor
65-
const references = await cursor
66-
// Avoid the first results when a page is provided in the request (URL)
67-
.skip(request.skip)
68-
// Avoid the last results when a limit is provided in the request query (URL)
69-
.limit(limit)
70-
// Changes the type from Cursor into Array, then saving data in memory
71-
.toArray();
89+
const references = await cursor.toArray();
7290
return { referencesCount, references };
7391
}
7492
});

0 commit comments

Comments
 (0)