перепиши функцию поиска так, чтобы она работала, как оригинал версия с json файлом. Вот оригинал версия и она РАБОТАЕТ. ТЕБЕ НУЖНО ОРИЕНТИРОВАТЬСЯ НА ОРИГИНАЛ ВЕРСИЮ, ЧТОБЫ SQL ВЕРСИЯ ЗАРАБОТАЛА:

function search(query = '', role = '', city = '', genre = '') {
  const data = fs.readFileSync('./db/musicians.json');
  
  const musicians = JSON.parse(data).musicians.map(musician => {
    return {
      name: musician.name,
      genre: musician.genre,
      originalName: musician.name,
      profileLink: `/profile/${musician.id}`,
      thumbnail: musician.thumbnail,
      soundcloud: musician.soundcloud,
      role: musician.role,
	  city: musician.city
      
    };
  });

  let results = [];

  if (query || role || city || genre) {
    const lowerQuery = query.toLowerCase();
    results = musicians.filter(musician => {
      const nameScore = musician.name.toLowerCase().startsWith(lowerQuery) ? 2 : musician.name.toLowerCase().includes(lowerQuery) ? 1 : 0;
      const genreScore = musician.genre.toLowerCase().startsWith(lowerQuery) ? 2 : musician.genre.toLowerCase().includes(lowerQuery) ? 1 : 0;
      
     return (
    nameScore + genreScore > 0 &&
    (role === "" || musician.role === role) &&
	(city === "" || (musician.city && musician.city.toLowerCase().trim() === city.toLowerCase().trim())) &&
    (genre === "" || musician.genre.toLowerCase() === genre.toLowerCase())
  );

    }).filter((a) => {
  if (role !== '' && a.role.toLowerCase() !== role.toLowerCase()) {
    return false;
  }
  if (city !== '' && a.city.toLowerCase() !== city.toLowerCase()) {
    return false;
  }
  if (genre !== '' && a.genre.toLowerCase() !== genre.toLowerCase()) {
    return false;
  }
  return true;
})
.sort((a, b) => {
  let scoreA = 0;
  let scoreB = 0;

  if (a.name.toLowerCase().includes(query)) {
    scoreA++;
  }
  if (a.genre.toLowerCase().includes(query)) {
    scoreA++;
  }
  if (b.name.toLowerCase().includes(query)) {
    scoreB++;
  }
  if (b.genre.toLowerCase().includes(query)) {
    scoreB++;
  }

  // Sort by score (descending)
  return scoreB - scoreA;
});

    // Remove duplicates
    results = results.filter((result, index, self) =>
      index === self.findIndex(r => (
        r.name === result.name && r.genre === result.genre && r.city === result.city
      ))
    );
  }

  return results;
}

а вот моя версия с sql и она дает ошибку code: 'ER_PARSE_ERROR',
  errno: 1064,
  sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?)' at line 1",
  sqlState: '42000',
  index: 0,
  sql: "SELECT * FROM users WHERE (name LIKE '%%' OR genre LIKE NULL) AND (role LIKE NULL) AND (LOWER(city) = '%Rock%' OR city IS NULL) AND (genre LIKE ?)"
}

sql версия поиска:

function search(term, role, city, genre, callback) {
  let query = term.toLowerCase();
  const queryValues = [
    `%${query}%`,
    role === '' ? null : `%${role}%`,
    city === '' ? null : city.toLowerCase().trim(),
    genre === '' ? '%' : `%${genre}%`
  ];

  const sql = `SELECT * FROM users WHERE (name LIKE ? OR genre LIKE ?) AND (role LIKE ?) AND (LOWER(city) = ? OR city IS NULL) AND (genre LIKE ?)`;

  connection.query(sql, queryValues, (err, result) => {
    if (err) {
      console.error('Ошибка при поиске: ', err);
      callback(err, []);
    } else {
      let results = result.map(musician => {
        return {
          name: musician.name,
          genre: musician.genre,
          originalName: musician.name,
          profileLink: `/profile/${musician.id}`,
          thumbnail: musician.thumbnail,
          soundcloud: musician.soundcloud,
          role: musician.role,
          city: musician.city
        };
      }).sort((a, b) => {
        const aNameScore = a.name.toLowerCase().startsWith(query) ? 2 : a.name.toLowerCase().includes(query) ? 1 : 0;
        const bNameScore = b.name.toLowerCase().startsWith(query) ? 2 : b.name.toLowerCase().includes(query) ? 1 : 0;
        const aGenreScore = a.genre.toLowerCase().startsWith(query) ? 2 : a.genre.toLowerCase().includes(query) ? 1 : 0;
        const bGenreScore = b.genre.toLowerCase().startsWith(query) ? 2 : b.genre.toLowerCase().includes(query) ? 1 : 0;

        // Sort by name score, then genre score, then location score (descending)
        if (aNameScore + aGenreScore + a.city < bNameScore + bGenreScore + b.city) {
          return 1;
        } else if (aNameScore + aGenreScore + a.city > bNameScore + bGenreScore + b.city) {
          return -1;
        } else {
          return 0;
        }
      });

      // Remove duplicates
      results = results.filter((result, index, self) =>
        index === self.findIndex(r => (
          r.name === result.name && r.genre === result.genre && r.city === result.city
        ))
      );

      callback(null, results);
    }
  });
}