Я пытаюсь настроить систему поиска для базы данных, в которой каждый элемент (код) в одной таблице имеет теги, сопоставленные отношением «многие ко многим». Я пытаюсь написать контроллер, «поиск», где я могу искать набор тегов, которые в основном действуют как ключевые слова, давая мне список элементов, где все элементы имеют указанные теги. Моя текущая функция невероятно наивна, в основном она состоит из извлечения всех кодов, которые отображаются как теги, затем добавления этих наборов, затем сортировки кодов по тому, сколько раз теги для каждого кода были найдены в строке запроса.
public List<Code> naiveSearch(String queryText) {
String[] tagMatchers = queryText.split(" ");
Set<Code> retained = new HashSet<>();
for (int i = 0; i < Math.min(tagMatchers.length, 4); i++) {
tagRepository.findAllByValueContaining(tagMatchers[i]).ifPresent((tags) -> {
tags.forEach(tag -> {
retained.addAll(tag.getCodes());
}
);
});
}
SortedMap<Integer, List<Code>> matches = new TreeMap<>();
List<Code> c;
for (Code code : retained) {
int sum = 0;
for (String tagMatcher : tagMatchers) {
for (Tag tag : code.getTags()) {
if (tag.getValue().contains(tagMatcher)) {
sum += 1;
}
}
}
c = matches.getOrDefault(sum, new ArrayList<>());
c.add(code);
matches.put(sum, c);
}
c = new ArrayList<>();
matches.values().forEach(c::addAll);
Collections.reverse(c);
return c;
}
Это довольно медленно и накладные расходы недопустимы. Мой предыдущий трюк заключался в основном в поиске описания для каждого кода в CRUDrepository
public interface CodeRepository extends CrudRepository<Code, Long> {
Optional<Code> findByCode(String codeId);
Optional<Iterable<Code>> findAllByDescriptionContaining(String query);
}
Однако это хрупко, поскольку порядок тегов, содержащих факторы, определяет, будет ли найден результат. например. Я хочу "высокий ... собака" == "собака ... высокий"