0
respostas

[Dúvida] Uma ajuda na questão de Query

Após expandir um pouco minha API com validações e uma classe de editoras resolvi fazer uma query para livros que poderia contar informações de editoras/autores/livros tinha um pouco de dificuldade de implementar. Gostaria de saber se tem alguma maneira mais prática de implementar. Implementei a partir dessa configuração de query

livroSchema.statics.queryConfig = {
  titulo: 'regex',
  lancamento: 'exact',
  'autor.name': 'regex',
  'autor.nationality': 'regex',
  'editora.razaoSocial': 'regex',
  'editora.nomeFantasia': 'regex',
  'editora.cnpj': 'exact',
  'editora.telefone': 'exact',
  'editora.email': 'regex',
  'editora.status': 'exact',
};
static async listBooksByQuery(req, res, next) {
    try {
      const { bookQuery, authorQuery, publisherQuery } = separateQueryParams(req.query);
      // If any of the book attributes were used as search parameters
      let bookList = [];

      if (Object.keys(bookQuery).length > 0) {
        if (bookQuery.titulo) bookQuery.titulo = new RegExp(bookQuery.titulo, 'i');
        bookList = await books.find(bookQuery).populate(['autor', 'editora']).exec();
        // Throw not found
        LivroController.checkEmpty(bookList);

        // Check if any properties related to author or publisher are included in the query
        if (Object.keys(authorQuery).length > 0 || Object.keys(publisherQuery).length > 0) {
          // Filter books that match the specified author and publisher
          bookList = await LivroController.filterByAuthorOrPublisher(bookList, authorQuery, publisherQuery);
        }
      } else {
        bookList = await LivroController.searchByAuthorOrPublisher(authorQuery, publisherQuery);
      }

      return res.status(200).json(bookList);
    } catch (error) {
      next(error);
    }
  }
function separateQueryParams(query) {
const bookQuery = {};
const authorQuery = {};
const publisherQuery = {};

for (const [key, value] of Object.entries(query)) {
  if (key.startsWith('autor.')) {
    const subKey = key.split('.').pop(); // get proper key for author collection
    authorQuery[subKey] = value;
  } else if (key.startsWith('editora.')) {
    const subKey = key.split('.').pop(); //get proper key for publisher collection
    publisherQuery[subKey] = value;
  } else {
    bookQuery[key] = value;
  }
}
return { bookQuery, authorQuery, publisherQuery };
}

export default separateQueryParams;
  static checkEmpty(list) {
    if (!list || list.length === 0) {
      throw new NotFound('No Books found within these parameters');
    }
  }
  static async filterByAuthorOrPublisher(bookList, authorQuery, publisherQuery) {
    // Get Author and Publisher ID based on the query
    const authorIds = await LivroController.getIdsByQuery(authorQuery, author);
    const publisherIds = await LivroController.getIdsByQuery(publisherQuery, publisher);

    // Filter the books found matching with authors and publishers
    return bookList.filter((book) => {
      const isAuthorMatch = authorIds ? authorIds.some((id) => id.equals(book.autor._id)) : true;
      const isPublisherMatch = publisherIds ? publisherIds.some((id) => id.equals(book.editora._id)) : true;

      return isAuthorMatch && isPublisherMatch;
    });
  }
  static async getIdsByQuery(query, model) {
   if (Object.keys(query).length > 0) {
     const results = await model.find(buildQuery(query, model));
     return results.map((item) => item._id);
   }
   return null;
 }
  static async searchByAuthorOrPublisher(authorQuery, publisherQuery) {
  // Get Author and Publisher ID based on the query
  const authorIds = await LivroController.getIdsByQuery(authorQuery, author);
  const publisherIds = await LivroController.getIdsByQuery(publisherQuery, publisher);

  // Search any book matches by author and publisher
  return books
    .find({
      ...(authorIds ? { autor: { $in: authorIds } } : {}),
      ...(publisherIds ? { editora: { $in: publisherIds } } : {}),
    })
    .populate(['autor', 'editora'])
    .exec();
}