Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Lucene неправильно сортирует результат


Автор: lamao 2.9.2014, 11:51
Делается запрос на выдачу четырех "похожих сущностей". За похожесть отвечает аннотация @DynamicBoost. Т.е. степень похожести определяется динамически по рейтингу и другим параметрам. Сама "важность" подсчитывается правильно (смотрел в дебаге). Но результат таков
  • 1) boost factor 104
  • 2) boost factor 105
  • 3) boost factor 6
  • 4) boost factor 4
От чего еще может зависеть порядок выдачи результатов кроме "веса"?

Lucene запрос таков 
productCategory.id:117 NOT id:100

То, что построил люцен в конце выглядит как
+(productCategory.id:117 -id:100) +(+packSpecificationStatus.id:2 +(validFrom:null validFrom:[* TO 20140902]))

Сам код запроса 
Код
public List<PackSpecification> searchByLuceneQuery(final String query, final int pageSize, final int pageNumber, final boolean returnOnlyApprovedAndValidPacks) throws ParseException {
        Assert.hasText(query);
        Assert.isTrue(0 < pageSize);
        Assert.isTrue(0 <= pageNumber);

        Session session = this.sessionFactory.getCurrentSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);

        Analyzer analyzer = fullTextSession.getSearchFactory().getAnalyzer(PackSpecification.class);
        org.apache.lucene.queryParser.QueryParser parser = new QueryParser(Version.LUCENE_36, "localizedList.name", analyzer);

        org.apache.lucene.search.Query parsedQuery = parser.parse(query);

        org.hibernate.Query hibQuery;
        if (returnOnlyApprovedAndValidPacks) {
            String now = DateTime.now().toString("yyyyMMdd");
            String selectOnlyPublicPacksQuery = String.format("packSpecificationStatus.id:%s AND (validFrom:%s OR validFrom:[* TO %s])",
                    PackSpecificationStatus.PackStatus.APPROVED.id, LuceneModelConstants.NULL, now);

            org.apache.lucene.search.Query selectOnlyPublicPacks = parser.parse(selectOnlyPublicPacksQuery);
            SearchFactory searchFactory = fullTextSession.getSearchFactory();
            QueryBuilder queryBuilder = searchFactory.buildQueryBuilder().forEntity(PackSpecification.class).get();

            org.apache.lucene.search.Query combinedQuery = queryBuilder
                    .bool()
                    .must(parsedQuery)
                    .must(selectOnlyPublicPacks)
                    .createQuery();

            // wrap Lucene query in a org.hibernate.Query
            hibQuery = fullTextSession.createFullTextQuery(combinedQuery, PackSpecification.class);
        } else {
            hibQuery = fullTextSession.createFullTextQuery(parsedQuery, PackSpecification.class);
        }

        hibQuery.setFirstResult(pageSize * pageNumber);
        hibQuery.setMaxResults(pageSize);

        return hibQuery.list();
    }


Динамическая стратегия определения веса:
Код
public class PackSpecificationBoostStrategy implements BoostStrategy {

    /** Base boost factor for any product */
    private final static float BASE_BOOST = 1f;

    /** Base boost factor for products with images */
    private final static float BASE_BOOST_FOR_PACK_WITH_IMAGES = 100f;

    /** Weight of raiting points */
    private final static float WEIGHT_OF_RATING_POINTS = 10f;


    @Override
    public float defineBoost(Object value) {
        float boostFactor = BASE_BOOST;
        if (value instanceof PackSpecification) {
            PackSpecification packSpecification = (PackSpecification) value;
            boostFactor = getBoostFactor(packSpecification);
        }
        return boostFactor;
    }

 
    private float getBoostFactor(PackSpecification packSpecification) {
        float result = BASE_BOOST;
        if (packSpecification.getGalleryList() != null && !packSpecification.getGalleryList().isEmpty()) {
            result = BASE_BOOST_FOR_PACK_WITH_IMAGES;
        }

        result += Rating.getRating(packSpecification.getVotes(), packSpecification.getMark()).id * WEIGHT_OF_RATING_POINTS;
        return result;
    }
}



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)