Я использую сочетание Hibernate Search и Apache Lucene. То, что я делаю, должно быть справедливым и легким, но я не могу достичь своей цели.Как заставить комбинацию из двух запросов быть ДОЛЖНЫ в Lucene?
У меня есть список строк (фраз), в которые я хочу запросить поле. Поле может содержать любую из этих строк. Между каждым полем должно быть только одно из них.
В MySQL это будет выглядеть следующим образом
select * from movies where (genres = 'name' or genres = 'name2') OR (actors = 'name' or actors = 'name2)' AND (actors = 'name' or actors = 'name2)
Так, если фильм содержал по крайней мере, один жанр дал и 1 актер дал или 2 актеров, то условие будет выполнено. Теперь в Lucene я сначала создаю BooleanQuery, объединяющий всех возможных участников с Occur.SHOULD
. Затем я создаю еще один BooleanQuery, объединяющий предыдущий BooleanQuery с другим (который, например, содержит все жанры).
В конце концов, я делаю то же самое дважды и добавляю оба эти BooleanQueries к новому, как с Occur.MUST
. Тем не менее, я получаю результаты, когда только одно из моих условий, если выполнено не менее 2. Как мне решить это?
private BooleanQuery getMatchQuery(List<String> list, String field) {
BooleanQuery bq = new BooleanQuery();
QueryBuilder qb = getFullTextEntityManager().getSearchFactory().buildQueryBuilder().forEntity(Movie.class).get();
for (String string : list) {
bq.add(qb.phrase().onField(field).sentence(string).createQuery(), Occur.SHOULD);
}
return bq;
}
private BooleanQuery getParamMatches(MovieDto dto, boolean genres){
BooleanQuery bq = new BooleanQuery();
bq.add(getMatchQuery(dto.getActors(), "actors"), Occur.SHOULD);
bq.add(getMatchQuery(dto.getDirectors(), "directors"), Occur.SHOULD);
bq.add(getMatchQuery(dto.getWriters(), "writers"), Occur.SHOULD);
if(genres){
bq.add(getMatchQuery(dto.getGenres(), "genres"), Occur.SHOULD);
}
return bq;
}
public List<Movie> test(MovieDto dto){
QueryBuilder qb = getFullTextEntityManager().getSearchFactory().buildQueryBuilder().forEntity(Movie.class).get();
log.info(getMatches(dto.getActors()));
BooleanQuery bq = new BooleanQuery();
bq.add(getParamMatches(dto, true), Occur.MUST);
bq.add(getParamMatches(dto, false), Occur.MUST);
javax.persistence.Query query = getFullTextEntityManager().createFullTextQuery(bq, Movie.class);
List<Movie> result = query.getResultList();
return result;
}
Это тот порядок, в котором я делаю это, как описано выше. Однако звонки выполняются снизу вверх. Результат запроса это одна:
+((actors:"marlon brando" actors:"al pacino" actors:"james caan" actors:"richard s castellano")
(directors:"francis ford coppola") (writers:"mario puzo screenplay" writers:"francis ford coppola screenplay" writers:"mario puzo novel")
(genres:crime genres:drama))
+((actors:"marlon brando" actors:"al pacino" actors:"james caan" actors:"richard s castellano")
(directors:"francis ford coppola") (writers:"mario puzo screenplay" writers:"francis ford coppola screenplay" writers:"mario puzo novel"))
Итак, как я могу идти о том, чтобы оба условия обязательно в комбинации, так что я не буду получать результаты, в которых только один актер, режиссер и т.д. присутствует? Я хочу, чтобы по крайней мере 2 параметра совпадали, по одному из каждого запроса.
Я только что понял, набрав все это подробно, что, вероятно, я уже делаю это правильно, но это не совсем применимо к моему делу, потому что query1 и query2 могут совпадать с одним и тем же актером, и все это будет верно , Кто-нибудь может это подтвердить? Если у кого-то есть решение для моей проблемы, которое я не смог правильно идентифицировать, это было бы даже лучше. – Schaka