#mongodb #api #strapi
#mongodb #API #strapi
Вопрос:
У меня есть массив идентификаторов, которые заполняются в array
.
Я пытаюсь отправить запрос API get в Strapi с фильтром, как показано ниже:
let listTagId = [];
tagOptions.map((tag) => {
if (inputValues[`${tag.nameTag}`]) {
listTagId.push(tag.id);
}
});
let filter = {
...cleanObject({
'tags.id': listTagId.length > 0 ? listTagId : null,
}
Где cleanObject
равно
function cleanObject(obj) {
let propNames = Object.getOwnPropertyNames(obj);
for (let i = 0; i < propNames.length; i ) {
var propName = propNames[i];
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName];
}
}
return obj;
}
Затем фильтр используется позже, с axios
помощью которого вызывается Strapi
async FIND(filter) {
try {
let query
if (filter) {
query = qs.stringify(filter)
}
let endpoint = `${this.apiEnpoint}${this.service}${query ? `?${query}` : ''}`
let { data } = await axios.get(endpoint,
{
headers: this.headers(this.getToken())
})
return { data }
} catch (error) {
return { error: this.getErrorMessage(error) }
}
}
Теги представляют собой коллекцию, которая имеет отношение к API-OBJECT
. Чего я хотел бы добиться, так это отфильтровать только те API-OBJECTs
, которые имеют все tags.id
включенные (tag.id1 и tag.id2 …).
На данный момент, если я использую логику, указанную выше (код), она использует логику OR, что означает, что она будет возвращать результаты с сервера, если объект имеет ОДИН из тегов в listTagId
.
Пример:
- Отправка listTagId =[‘1223’, ‘345’], в настоящее время он извлекает все объекты с идентификаторами ‘1223’ или ‘345’. Таким образом, объект может иметь отношение к тегу только с тегом 1223, и он все равно будет восстановлен. Неправильное поведение для меня.
- Отправка listTagId =[‘1223’, ‘345’], вызов должен извлекать только объекты, имеющие теги с идентификаторами ‘1223’ И ‘345’.
Извлечение из консоли:
'GET /api-end-point/count?_where[category_contains]=housesamp;_where[tags.id][0]=60420fc8c4bed44584638decamp;_where[tags.id][1]=60420febc4bed44584638dedamp;_where[tags.id][2]=6042151fbea9601908f2c774amp;_where[tags.id][3]=60421520bea9601908f2c775amp;_where[tags.id][4]=60421521bea9601908f2c776amp;_where[tags.id][5]=60421522bea9601908f2c777amp;_where[tags.id][6]=60421522bea9601908f2c778 (562 ms)'
Я пытался использовать tags.id_in
, но это дало те же результаты, что и сейчас.
Как я должен изменить запрос для ‘tags.id — для того, чтобы извлечь нужные элементы?
Ответ №1:
Мне удалось обойти это, настроив контроллер, поскольку оказалось, что у Strapi нет AND
логики, как я нашел. Хотя мне не нравится, что для этого потребуется много ресурсов, поскольку массивы обновляются и повторяются довольно много раз. Если есть другие предложения, пожалуйста, дайте мне знать.
Что я здесь делаю, так это убираю ограничение, чтобы я получал все объекты, а затем:
- Получение всех объектов, у которых есть все теги (с использованием ИЛИ), и наличие остальных фильтров.
- Как только размер уменьшается на что-то, я перебираю элементы и нахожу те, у которых есть все идентификаторы тегов.
- Я не хочу проходить через каждый и один, поэтому, как только я достиг предела, я вырываюсь из цикла foreach.
«использовать строгий»;
const { sanitizeEntity } = require(«strapi-utils»);
module.exports = { асинхронный поиск (ctx) { пусть теги; пусть сущности; пусть tagEntities = []; пусть limit; если (ctx.query?._limit) { limit = ctx.query._limit; удалить ctx.query._limit; }
if (ctx.query?._where?.tags) { tags = ctx.query._where.tags; delete ctx.query._where.tags; ctx.query._where["tags.id_in"] = tags; } if (ctx.query._q) { entities = await strapi.services["custom-controller"].search(ctx.query); } else { entities = await strapi.services["custom-controller"].find(ctx.query); } tagEntities = []; try { entities.forEach((element) => { if (limit <= 0) throw BreakException; let newListId = []; element.tags.forEach((tag) => newListId.push(tag?.id)); var result = tags?.every((val) => { return newListId.indexOf(val) >= 0; }); if (!tags) { tagEntities.push(element); limit--; } if (result) { tagEntities.push(element); limit--; } }); } catch (e) {} return tagEntities.map((entity) => sanitizeEntity(entity, { model: strapi.models["custom-controller"] }) ); }, };
Комментарии:
1. Просто подтверждая, что я должен был сделать то же самое (пользовательский контроллер). Помимо
and/or
необходимого контроля, это также включает «глубокий поиск», который Strapi до v4 был слабым через официальный API. С Strapi V4 я думаю, что они выпустили новые вещи, которые могут помочь? Для начала есть эта статья: strapi.io/blog/deep-filtering-alpha-26