So I managed to implement a hacked-together solution on the Backend.
Whether this is the correct way of solving this issue, I don’t know. In fact, I doubt it.
Best I could come up with.
Problem:
Extend the find/search function to search with relational documents in MongoDB
Solution:
- Retrieve populated documents. (Main document and their relational documents)
- Search through the array of documents and store result.
- Return the result as a response.
// in services file - /api/onts/services/onts.js
const pop = [
{
path: "address_unit",
populate: {
path: "address_complex",
},
},
{
path: "services",
populate: {
path: "vlan",
},
},
];
module.exports = {
customFind: async (params, populate) => {
let results;
let filteredResults;
results = await strapi.query("onts").find(null, pop); // Step 1
filteredResults = searchArrayOfObjects(results, params); // Step 2
return filteredResults; // Step 3
},
};
// in controllers file - /api/onts/controllers/onts.js
module.exports = {
customFind: async (ctx) => {
let result;
result = await strapi.services.onts.customFind(ctx.params.find);
return result;
},
};
// in routes file - /api/onts/config/routes.json
{
"routes": [
{
"method": "GET",
"path": "/onts/:find",
"handler": "onts.customFind",
"config": {
"policies": []
}
},
... //other routes
]
}
For those interested in knowing what search function I used in Step 2 searchArrayOfObjects(results, params), here is the code.
function searchSingleObject(object, text) {
let flag;
for (let key in object) {
if (object[key] !== null) {
if (typeof object[key] === "object") {
if (object[key].length > 0 || object[key].length !== undefined) {
flag = searchArrayOfObjects(object[key], text);
}
flag = searchSingleObject(object[key], text);
if (flag) break;
} else {
flag = false;
flag =
object[key].toString().toLowerCase().indexOf(text.toLowerCase()) > -1;
if (flag) break;
}
}
}
return flag;
}
function searchArrayOfObjects(objectList, text) {
if (undefined === text || text === "" || text === undefined)
return objectList;
const res = objectList.filter((object) => {
return searchSingleObject(object, text);
});
return res;
}
Anyway, it works.
Please let me know if there are better solutions available.