Как я могу отправить идентификаторы тегов массива в Strapi, используя И логику не ИЛИ логику между ними? [MongoDB]

#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 .

Пример:

  1. Отправка listTagId =[‘1223’, ‘345’], в настоящее время он извлекает все объекты с идентификаторами ‘1223’ или ‘345’. Таким образом, объект может иметь отношение к тегу только с тегом 1223, и он все равно будет восстановлен. Неправильное поведение для меня.
  2. Отправка 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 логики, как я нашел. Хотя мне не нравится, что для этого потребуется много ресурсов, поскольку массивы обновляются и повторяются довольно много раз. Если есть другие предложения, пожалуйста, дайте мне знать.

Что я здесь делаю, так это убираю ограничение, чтобы я получал все объекты, а затем:

  1. Получение всех объектов, у которых есть все теги (с использованием ИЛИ), и наличие остальных фильтров.
  2. Как только размер уменьшается на что-то, я перебираю элементы и нахожу те, у которых есть все идентификаторы тегов.
  3. Я не хочу проходить через каждый и один, поэтому, как только я достиг предела, я вырываюсь из цикла 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